zoukankan      html  css  js  c++  java
  • RSA公钥加密私钥解密

    公司的项目需要电科院测评,必须保证数据的完整性和保密性,为这两个特性不得不搞个RSA+SHA1加密。

    页面处理过程:

    每次登录前,先向后端发送请求,由RSA生成一对公钥和私钥,获取公钥中的模modulus和指数exponent,然后传到前端,私钥存入当前请求的session中。前端使用security.js先根据后传过来模和指数生成公钥,然后用公钥加密密码。

    对加密后的数据进行SHA1校验,计算出HashCode,然后进行登录时将哈希值一并传到后端,后端从请求中解析出数据再次计算HashCode并于页面传递来的HashCode进行比较,若不一致则数据可能被篡改。再使用私钥解密,验证密码的正确性。

    首先必不可少的就是jar包,和js文件

    jar 包 bcprov-jdk16-146.jar 和commons-codec-1.2.jar

    js:jquery.min.js,SHA1.js和security.js

    Java生成秘钥工具类RSAUtils

    package com.founder.mrp.util;
    
    import java.math.BigInteger;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.RSAPrivateKeySpec;
    import java.security.spec.RSAPublicKeySpec;
    import java.util.HashMap;
    
    import javax.crypto.Cipher;

      /**
      * @Auther: hanwl
      * @Date: 20190822
      * @Description:
      */

    public class RSAUtils {
        /**
         *    * 生成公钥和私钥   
         * * @throws NoSuchAlgorithmException  *   
         */
        public static HashMap<String, Object> getKeys()
                throws NoSuchAlgorithmException {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            HashMap<String, Object> map = new HashMap<String, Object>();
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            keyPairGen.initialize(1024);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
            map.put("public", publicKey);
            map.put("private", privateKey);
            return map;
        }
    
        /**
         *    * 使用模和指数生成RSA公钥   
         * * @param modulus  模   
         * * @param exponent  指数   *
         * @return   
         */
        public static RSAPublicKey getPublicKey(String modulus, String exponent) {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            try {
                BigInteger b1 = new BigInteger(modulus);
                BigInteger b2 = new BigInteger(exponent);
                KeyFactory keyFactory = KeyFactory.getInstance("RSA",
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());
                RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
                return (RSAPublicKey) keyFactory.generatePublic(keySpec);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         *    * 使用模和指数生成RSA私钥   
         * * /None/NoPadding  
         * * @param modulus  
         * 模   * @param
         * exponent指数   * @return   
         */
        public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
            try {
                Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
                BigInteger b1 = new BigInteger(modulus);
                BigInteger b2 = new BigInteger(exponent);
                KeyFactory keyFactory = KeyFactory.getInstance("RSA",
                        new org.bouncycastle.jce.provider.BouncyCastleProvider());
                RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
                return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         *    * 公钥加密   *  
         * * @param data   
         * * @param publicKey   
         * * @return   
         * * @throws
         * Exception   
         */
        public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
                throws Exception {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("RSA",
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 模长
            int key_len = publicKey.getModulus().bitLength() / 8;
            // 加密数据长度 <= 模长-11
            String[] datas = splitString(data, key_len - 11);
            String mi = "";
            // 如果明文长度大于模长-11则要分组加密
            for (String s : datas) {
                mi += bcd2Str(cipher.doFinal(s.getBytes()));
            }
            return mi;
        }
    
        /**
         *    * 私钥解密   *  
         * * @param data   
         * * @param privateKey   
         * * @return   
         * * @throws
         * Exception   
         */
        public static String decryptByPrivateKey(String data,
                RSAPrivateKey privateKey) throws Exception {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("RSA",
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 模长
            int key_len = privateKey.getModulus().bitLength() / 8;
            byte[] bytes = data.getBytes();
            byte[] bcd = ASCII_To_BCD(bytes, bytes.length);
            // System.err.println(bcd.length);
            // 如果密文长度大于模长则要分组解密
            String ming = "";
            byte[][] arrays = splitArray(bcd, key_len);
            for (byte[] arr : arrays) {
                ming += new String(cipher.doFinal(arr));
            }
            return ming;
        }
    
        /**
         *    * ASCII码转BCD码   *  
         */
        public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
            byte[] bcd = new byte[asc_len / 2];
            int j = 0;
            for (int i = 0; i < (asc_len + 1) / 2; i++) {
                bcd[i] = asc_to_bcd(ascii[j++]);
                bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
            }
            return bcd;
        }
    
        public static byte asc_to_bcd(byte asc) {
            byte bcd;
    
            if ((asc >= '0') && (asc <= '9'))
                bcd = (byte) (asc - '0');
            else if ((asc >= 'A') && (asc <= 'F'))
                bcd = (byte) (asc - 'A' + 10);
            else if ((asc >= 'a') && (asc <= 'f'))
                bcd = (byte) (asc - 'a' + 10);
            else
                bcd = (byte) (asc - 48);
            return bcd;
        }
    
        /**
         *    * BCD转字符串   
         */
        public static String bcd2Str(byte[] bytes) {
            char temp[] = new char[bytes.length * 2], val;
    
            for (int i = 0; i < bytes.length; i++) {
                val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
                temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
    
                val = (char) (bytes[i] & 0x0f);
                temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
            }
            return new String(temp);
        }
    
        /**
         *    * 拆分字符串   
         */
        public static String[] splitString(String string, int len) {
            int x = string.length() / len;
            int y = string.length() % len;
            int z = 0;
            if (y != 0) {
                z = 1;
            }
            String[] strings = new String[x + z];
            String str = "";
            for (int i = 0; i < x + z; i++) {
                if (i == x + z - 1 && y != 0) {
                    str = string.substring(i * len, i * len + y);
                } else {
                    str = string.substring(i * len, i * len + len);
                }
                strings[i] = str;
            }
            return strings;
        }
    
        /**
         *    *拆分数组  
         */
        public static byte[][] splitArray(byte[] data, int len) {
            int x = data.length / len;
            int y = data.length % len;
            int z = 0;
            if (y != 0) {
                z = 1;
            }
            byte[][] arrays = new byte[x + z][];
            byte[] arr;
            for (int i = 0; i < x + z; i++) {
                arr = new byte[len];
                if (i == x + z - 1 && y != 0) {
                    System.arraycopy(data, i * len, arr, 0, y);
                } else {
                    System.arraycopy(data, i * len, arr, 0, len);
                }
                arrays[i] = arr;
            }
            return arrays;
        }
    
        public static void main(String[] args) throws Exception {
            HashMap<String, Object> map = getKeys();
            // 生成公钥和私钥
            RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
            RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
    
            //
            String modulus = publicKey.getModulus().toString();
            System.out.println("pubkey modulus=" + modulus);
            // 公钥指数
            String public_exponent = publicKey.getPublicExponent().toString();
            System.out.println("pubkey exponent=" + public_exponent);
            // 私钥指数
            String private_exponent = privateKey.getPrivateExponent().toString();
            System.out.println("private exponent=" + private_exponent);
            // 明文
            String ming = "founder123";
            // 使用模和指数生成公钥和私钥
            RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);
            RSAPrivateKey priKey = RSAUtils.getPrivateKey(modulus,private_exponent);
    
            // 加密后的密文
            String mi = RSAUtils.encryptByPublicKey(ming, pubKey);
            System.err.println("mi=" + mi);
            // 解密后的明文
            String ming2 = RSAUtils.decryptByPrivateKey(mi, priKey);
            System.err.println("ming2=" + ming2);
        }
    }

    Java计算SHA-1哈希值工具类SHA1Utils

    package com.founder.mrp.util;
    
    import java.io.IOException;
    import java.security.GeneralSecurityException;
    import java.security.MessageDigest;
    
    /**
     * @Auther: hanwl
     * @Date: 20190822
     * @Description:
     */
    public class SHA1Utils {
        public static String getSHA1Digest(String data) throws IOException {
            byte[] bytes = null;
            try {
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                bytes = md.digest(data.getBytes("utf-8"));
            } catch (GeneralSecurityException gse) {
                throw new IOException(gse);
            }
            return byte2hex(bytes);
        }
    
        /**
         * 二进制转十六进制字符串
         *
         * @param bytes
         * @return
         */
        private static String byte2hex(byte[] bytes) {
            StringBuilder sign = new StringBuilder();
            for (int i = 0; i < bytes.length; i++) {
                String hex = Integer.toHexString(bytes[i] & 0xFF);
                if (hex.length() == 1) {
                    sign.append("0");
                }
                sign.append(hex.toUpperCase());
            }
            return sign.toString();
        }
    }

    前端ajax请求登录

      登录页面需要引入js,security.js用模和指数生成公钥和加密,sha1.js计算哈希值

    <script src="${pageContext.request.contextPath}/resources/bootstrap/js/security.js"></script>
    <script src="${pageContext.request.contextPath}/resources/bootstrap/js/SHA1.js"></script>

      Form表单

     

    <!-- BEGIN LOGIN -->
        <div class="content"  id="loginForm">
            <!-- BEGIN LOGIN FORM -->
            <form class="form-vertical login-form "  method="post">           
                <div class="control-group">
                    <div class="controls">
                        <div class="input-icon left">
                            <img  src="${pageContext.request.contextPath}/resources/images/user.png"  />
                            <input class="m-wrap placeholder-no-fix" type="text" value="" name="username" id="username" />
                            <span class="placehold" id="username_place">用户名</span>
                            <input type="text" value="" id="username_fade" class="fade_input" tabindex="-1"/>
                        </div>
                    </div>
                </div>
                <div class="control-group">
                    <div class="controls">
                        <div class="input-icon left">
                            <img  src="${pageContext.request.contextPath}/resources/images/lock.png"  class="lock"/>
                            <input class="m-wrap placeholder-no-fix" type="password" value="" name="password" id="pwd"/>
                            <span class="placehold" id="pwd_place">&nbsp;&nbsp;&nbsp;</span>
                            <input type="password" value="" id="username_fade" class="fade_input" tabindex="-1"/>
                        </div>
                    </div>
                </div>
    
                <div class="form-actions" style="height:60px;">
                    <label class="checkbox" style="display: none;">
                        <input type="checkbox" name="remember" value="1"/>自动登录
                    </label>    
                    <a href="/PodCloud/findPassWord.action" style="display: none;"> 找回密码</a>        
                    <a id="downloadClient" class="pull-right">下载客户端</a>
                    
                    <div  id="clients"  class="pull-right hide">
                        <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAARhwAAEYcBQV9idQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAACTSURBVCiRvZIxCgJBEAS7lovMxFDNPEzN/ML9wJcs7JP0L/oBX2CkkScm1wYiyDFsJHZYMzUw0ChIzrlNKXXABljbXgIz2xNKKXtgJWkuaWq7AY6SttGxBth9A2CIFj9JteFPhAa4jtjD9hloQ8F2P2I9cA/4W5C0GLHB9i3gkv7xdLJ9kHSSdJH0tO2aQARr1XgBYQk33CTW7RkAAAAASUVORK5CYII="
                             style="vertical-align: top;padding-top: 2px;padding-right: 5px;"/>
                        <a class="zoom" href="downloadClient.action?clientType=PublisherClient"  >
                            <img src="${pageContext.request.contextPath}/resources/images/PublisherClient.png" width="60"  alt="出版管理客户端" title="出版管理客户端">
                        </a>
                        <a class="zoom" href="downloadClient.action?clientType=TypeSettingClient"  >
                            <img src="${pageContext.request.contextPath}/resources/images/TypeSettingClient.png" width="60" alt="排版客户端" title="排版客户端">
                        </a>
                        <a class="zoom" href="downloadClient.action?clientType=PrinterClient"  >
                            <img src="${pageContext.request.contextPath}/resources/images/PrinterClient.png"  width="60" alt="印厂客户端"  title="印厂客户端">
                        </a>
    
                        <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAOCAYAAAAbvf3sAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAPugAAD7oBsgpXUQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAENSURBVCiRjZAhS0NhGIWf821s0WSQiUFvtQvjVn/B9gsMBv/BvWNcy2WIyaQIJtsNDoNYx8Bgs2j6FAymgUUNF+99DTJYcPideN7z8B6OWKJ+v9+IomhoZuuj0Whv7rtlQBRFR8DQOfe46P8JZFnmgH1gMpvNThZvAhgMBltVVaVAR9KzmT0BO5LezWwb+JZ0kef5pZIkWTOzB2B1Wb25zKznzCwJCQNj7/3YAbsBYSQdFkVROWAjBCjL8g1+V/oMAZrNZhfAmdl9YKXjNE07DjgPAYDNuq5vnff+GvCBX05dURSVpAOg/ic/abVaZw2A6XTq4zh+AbqSXiVdSboxsw9JK8Bdu93uZVn29QOyWl520hqg9QAAAABJRU5ErkJggg=="
                             style="vertical-align: top;padding-left: 10px;"/>
                        <a class="zoom" href="downloadClient.action?clientType=PublisherClientMAC"  >
                            <img src="${pageContext.request.contextPath}/resources/images/PublisherClient.png" width="60"  alt="出版管理客户端(MAC版)" title="出版管理客户端(MAC版)">
                        </a>
                        <a class="zoom" href="downloadClient.action?clientType=TypeSettingClientMAC"  >
                            <img src="${pageContext.request.contextPath}/resources/images/TypeSettingClient.png" width="60" alt="排版客户端(MAC版)"  title="排版客户端(MAC版)">
                        </a>
                    </div>
                </div>
    
                <div class="form-actions h-center">
                    <button type="submit" class="btn green " id="btnLogin" name="btnLogin">
                      登录 
                    </button>
                </div>
            </form>
            <!-- END LOGIN FORM -->
            <input id="publicKeyExponent" value="" type="hidden"> <%-- 后台传过来的公钥 --%> 
            <input id="publicKeyModulus" value="" type="hidden">  <%-- 后台传过来的模 --%>
        </div>
        <!-- END LOGIN -->

      ajax请求

    var Login = function () {    
        return {            
            init: function () {           
               $('.login-form').validate({
                    errorElement: 'label', //default input error message container
                    errorClass: 'help-inline', // default input error message class
                    focusInvalid: false, // do not focus the last invalid input
                    rules: {
                        username: {
                            required: true
                        },
                        password: {
                            required: true
                        },
                        remember: {
                            required: false
                        }
                    },
    
                    messages: {
                        username: {
                            required: "请输入用户名"
                        },
                        password: {
                            required: "请输入密码"
                        }
                    },
    
                    invalidHandler: function (event, validator) { //display error alert on form submit   
                        $(".login-form .alert-error #errorMsg").text('用户名或密码为空');
                        $('.alert-error', $('.login-form')).show();
                    },
    
                    highlight: function (element) { // hightlight error inputs
                        $(element)
                            .closest('.control-group').addClass('error'); // set error class to the control group
                    },
    
                    success: function (label) {
                        label.closest('.control-group').removeClass('error');
                        label.remove();
                       
                    },
    
                    errorPlacement: function (error, element) {
    //                    error.addClass('help-small no-left-padding').appendTo(element.closest('.input-icon'));
                    },
    
                    submitHandler: function (form) {
                        var btn=$('#btnLogin');
                        var username = $.trim($("#username").val());
                        var password = $.trim($("#pwd").val());
                        btn.attr('disabled','disabled').html('正在登录...');                    
                        var obj=this;
                          $.ajax({
                              url: "/PodCloud/loginRSA.action",
                              type:"POST",                                            
                              dataType:'json',      
                              error:function(XMLHttpRequest, textStatus, errorThrown){
                                  console.log(XMLHttpRequest.status);
                                  console.log(XMLHttpRequest.readyState);
                                  console.log(textStatus);
                              },
                              success: function(data)
                              {                                                          
                                  if(data.code==0)
                                      {
                                          $("#publicKeyExponent").val(data.data[0]);
                                          $("#publicKeyModulus").val(data.data[1]);
                                          
                                          //RSA加密
                                          var publicKeyExponent=$("#publicKeyExponent").val();
                                          var publicKeyModulus=$("#publicKeyModulus").val();
                                          RSAUtils.setMaxDigits(200);
                                          var key = new RSAUtils.getKeyPair(publicKeyExponent, "", publicKeyModulus);
                                          var userNameEncrypt = RSAUtils.encryptedString(key,username.split("").reverse().join("")); //用户名加密
                                          var userPwdEncrypt= RSAUtils.encryptedString(key,password.split("").reverse().join("")); //密码加密
                                          var userNamePwdHashcode = hex_sha1(username+password); //用户名和密码 计算哈希值
                                          $.ajax({
                                              url: "/PodCloud/login.action",
                                              type:"POST",                                            
                                              dataType:'json',
                                              data:{"username":userNameEncrypt,"pwd":userPwdEncrypt,"userNamePwdHashcode":userNamePwdHashcode,"autoLogin":$('.form-actions :checked').length>0},
                                              cache: false,       
                                              error:function(XMLHttpRequest, textStatus, errorThrown){
                                                  console.log(XMLHttpRequest.status);
                                                  console.log(XMLHttpRequest.readyState);
                                                  console.log(textStatus);
                                              },
                                              success: function(data)
                                              {    
                                                  //btn.removeAttr('disabled').html('登录 <i class="m-icon-swapright m-icon-white"></i>');                        
                                                  if(data.code==0)
                                                      {
                                                        var redirect=$('#hdRedirectUrl').val();
                                                        redirect?location.href=decodeURIComponent(redirect):location.href="/PodCloud/home.action";                                      
                                                      }
                                                  else
                                                      {
                                                              $('.alert-error', $('.login-form')).show().find('span').text(data.message);
                                                      }
                                              }
                                          });
                                          
                                      }
                                  else
                                      {
                                              $('.alert-error', $('.login-form')).show().find('span').text("获取密钥失败!");
                                      }
                              }
                          });
                    }
                });             
            }
        };
    }();

    后台生成秘钥controller

    //生成登陆用的RSA公钥 密钥
        @RequestMapping(value="/loginRSA",method=RequestMethod.POST)
        @ResponseBody
        public AjaxResponse<List<String>> loginRSA(HttpServletRequest request,HttpServletResponse response){
            String publicKeyExponent="";
            String publicKeyModulus="";
            try {
                HashMap<String, Object> map = RSAUtils.getKeys();
                //生成公钥和私钥    
                RSAPublicKey publicKey = (RSAPublicKey) map.get("public");
                RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");
                //私钥保存在session中,用于解密  
                request.getSession().setAttribute("privateKeyLogin", privateKey);
                //公钥信息保存在页面,用于加密 公钥指数  
                publicKeyExponent = publicKey.getPublicExponent().toString(16); //此处toString中的16按实际情况增加
                System.out.println("公钥指数:"+publicKeyExponent);
                //模 
                publicKeyModulus = publicKey.getModulus().toString(16); //此处toString中的16按实际情况增加
                System.out.println("公钥模:"+publicKeyModulus);
                // request.getSession().setAttribute("publicKeyExponent", publicKeyExponent);  
                //request.getSession().setAttribute("publicKeyModulus", publicKeyModulus); 
            } catch (Exception e) {
                log.debug("RSA生成公钥错误",e);
            }
            List<String> list=new ArrayList<String>();
            list.add(publicKeyExponent);
            list.add(publicKeyModulus);
            if(list!=null&&list.size()>0){
                return AjaxResponse.success(list);
            }else{
                return AjaxResponse.fail(-1,"获取密钥失败!");
            }
            
        }

    后台验证登录controller

    @RequestMapping(value="/login",method=RequestMethod.POST)
        @ResponseBody
        public AjaxResponse<String> login(
                @RequestParam(value="username",required=false) String username,
                @RequestParam(value="pwd",required=false) String password,
                @RequestParam(value="userNamePwdHashcode",required=false) String userNamePwdHashcode,
                @RequestParam(value="autoLogin",required=false) Boolean autoLogin,
                HttpServletRequest request,
                HttpServletResponse response) {
            log.debug("username:"+username+";password:"+password);
            int clientType = ClinetType.Web.getTypeValue();//WEB client =0
            
            try {
                //私钥解密
                RSAPrivateKey privateKey = (RSAPrivateKey) request.getSession().getAttribute("privateKeyLogin");
                username = RSAUtils.decryptByPrivateKey(username, privateKey);
                password=RSAUtils.decryptByPrivateKey(password, privateKey);
                
                String userNameAndPwdHashcode = SHA1Utils.getSHA1Digest(username+password).toLowerCase();
                if(!userNameAndPwdHashcode.equals(userNamePwdHashcode)){
                    return AjaxResponse.fail(-8, "数据可能被篡改,拒绝登陆!");
                }
    //            username = AesUtil.aesDecrypt(username); //后台解密
    //            password = AesUtil.aesDecrypt(password); //后台解密 
            } catch (Exception e) {
                log.debug("RSA解密失败",e);
            }
            
            AjaxResponse<String> reg = loginlogoutSrv.saveLogin(request, response, "", false, username, password, autoLogin,false,clientType);
            log.debug("WEB登陆service调用完毕");
            return reg;
            }

    附件security.js

    (function($w) {
    
    if(typeof $w.RSAUtils === 'undefined')
        var RSAUtils = $w.RSAUtils = {};
    
    var biRadixBase = 2;
    var biRadixBits = 16;
    var bitsPerDigit = biRadixBits;
    var biRadix = 1 << 16; // = 2^16 = 65536
    var biHalfRadix = biRadix >>> 1;
    var biRadixSquared = biRadix * biRadix;
    var maxDigitVal = biRadix - 1;
    var maxInteger = 9999999999999998;
    
    //maxDigits:
    //Change this to accommodate your largest number size. Use setMaxDigits()
    //to change it!
    //
    //In general, if you're working with numbers of size N bits, you'll need 2*N
    //bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need
    //
    //1024 * 2 / 16 = 128 digits of storage.
    //
    var maxDigits;
    var ZERO_ARRAY;
    var bigZero, bigOne;
    
    var BigInt = $w.BigInt = function(flag) {
        if (typeof flag == "boolean" && flag == true) {
            this.digits = null;
        } else {
            this.digits = ZERO_ARRAY.slice(0);
        }
        this.isNeg = false;
    };
    
    RSAUtils.setMaxDigits = function(value) {
        maxDigits = value;
        ZERO_ARRAY = new Array(maxDigits);
        for (var iza = 0; iza < ZERO_ARRAY.length; iza++) ZERO_ARRAY[iza] = 0;
        bigZero = new BigInt();
        bigOne = new BigInt();
        bigOne.digits[0] = 1;
    };
    RSAUtils.setMaxDigits(20);
    
    //The maximum number of digits in base 10 you can convert to an
    //integer without JavaScript throwing up on you.
    var dpl10 = 15;
    
    RSAUtils.biFromNumber = function(i) {
        var result = new BigInt();
        result.isNeg = i < 0;
        i = Math.abs(i);
        var j = 0;
        while (i > 0) {
            result.digits[j++] = i & maxDigitVal;
            i = Math.floor(i / biRadix);
        }
        return result;
    };
    
    //lr10 = 10 ^ dpl10
    var lr10 = RSAUtils.biFromNumber(1000000000000000);
    
    RSAUtils.biFromDecimal = function(s) {
        var isNeg = s.charAt(0) == '-';
        var i = isNeg ? 1 : 0;
        var result;
        // Skip leading zeros.
        while (i < s.length && s.charAt(i) == '0') ++i;
        if (i == s.length) {
            result = new BigInt();
        }
        else {
            var digitCount = s.length - i;
            var fgl = digitCount % dpl10;
            if (fgl == 0) fgl = dpl10;
            result = RSAUtils.biFromNumber(Number(s.substr(i, fgl)));
            i += fgl;
            while (i < s.length) {
                result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10),
                        RSAUtils.biFromNumber(Number(s.substr(i, dpl10))));
                i += dpl10;
            }
            result.isNeg = isNeg;
        }
        return result;
    };
    
    RSAUtils.biCopy = function(bi) {
        var result = new BigInt(true);
        result.digits = bi.digits.slice(0);
        result.isNeg = bi.isNeg;
        return result;
    };
    
    RSAUtils.reverseStr = function(s) {
        var result = "";
        for (var i = s.length - 1; i > -1; --i) {
            result += s.charAt(i);
        }
        return result;
    };
    
    var hexatrigesimalToChar = [
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z'
    ];
    
    RSAUtils.biToString = function(x, radix) { // 2 <= radix <= 36
        var b = new BigInt();
        b.digits[0] = radix;
        var qr = RSAUtils.biDivideModulo(x, b);
        var result = hexatrigesimalToChar[qr[1].digits[0]];
        while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
            qr = RSAUtils.biDivideModulo(qr[0], b);
            digit = qr[1].digits[0];
            result += hexatrigesimalToChar[qr[1].digits[0]];
        }
        return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
    };
    
    RSAUtils.biToDecimal = function(x) {
        var b = new BigInt();
        b.digits[0] = 10;
        var qr = RSAUtils.biDivideModulo(x, b);
        var result = String(qr[1].digits[0]);
        while (RSAUtils.biCompare(qr[0], bigZero) == 1) {
            qr = RSAUtils.biDivideModulo(qr[0], b);
            result += String(qr[1].digits[0]);
        }
        return (x.isNeg ? "-" : "") + RSAUtils.reverseStr(result);
    };
    
    var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f'];
    
    RSAUtils.digitToHex = function(n) {
        var mask = 0xf;
        var result = "";
        for (i = 0; i < 4; ++i) {
            result += hexToChar[n & mask];
            n >>>= 4;
        }
        return RSAUtils.reverseStr(result);
    };
    
    RSAUtils.biToHex = function(x) {
        var result = "";
        var n = RSAUtils.biHighIndex(x);
        for (var i = RSAUtils.biHighIndex(x); i > -1; --i) {
            result += RSAUtils.digitToHex(x.digits[i]);
        }
        return result;
    };
    
    RSAUtils.charToHex = function(c) {
        var ZERO = 48;
        var NINE = ZERO + 9;
        var littleA = 97;
        var littleZ = littleA + 25;
        var bigA = 65;
        var bigZ = 65 + 25;
        var result;
    
        if (c >= ZERO && c <= NINE) {
            result = c - ZERO;
        } else if (c >= bigA && c <= bigZ) {
            result = 10 + c - bigA;
        } else if (c >= littleA && c <= littleZ) {
            result = 10 + c - littleA;
        } else {
            result = 0;
        }
        return result;
    };
    
    RSAUtils.hexToDigit = function(s) {
        var result = 0;
        var sl = Math.min(s.length, 4);
        for (var i = 0; i < sl; ++i) {
            result <<= 4;
            result |= RSAUtils.charToHex(s.charCodeAt(i));
        }
        return result;
    };
    
    RSAUtils.biFromHex = function(s) {
        var result = new BigInt();
        var sl = s.length;
        for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
            result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4)));
        }
        return result;
    };
    
    RSAUtils.biFromString = function(s, radix) {
        var isNeg = s.charAt(0) == '-';
        var istop = isNeg ? 1 : 0;
        var result = new BigInt();
        var place = new BigInt();
        place.digits[0] = 1; // radix^0
        for (var i = s.length - 1; i >= istop; i--) {
            var c = s.charCodeAt(i);
            var digit = RSAUtils.charToHex(c);
            var biDigit = RSAUtils.biMultiplyDigit(place, digit);
            result = RSAUtils.biAdd(result, biDigit);
            place = RSAUtils.biMultiplyDigit(place, radix);
        }
        result.isNeg = isNeg;
        return result;
    };
    
    RSAUtils.biDump = function(b) {
        return (b.isNeg ? "-" : "") + b.digits.join(" ");
    };
    
    RSAUtils.biAdd = function(x, y) {
        var result;
    
        if (x.isNeg != y.isNeg) {
            y.isNeg = !y.isNeg;
            result = RSAUtils.biSubtract(x, y);
            y.isNeg = !y.isNeg;
        }
        else {
            result = new BigInt();
            var c = 0;
            var n;
            for (var i = 0; i < x.digits.length; ++i) {
                n = x.digits[i] + y.digits[i] + c;
                result.digits[i] = n % biRadix;
                c = Number(n >= biRadix);
            }
            result.isNeg = x.isNeg;
        }
        return result;
    };
    
    RSAUtils.biSubtract = function(x, y) {
        var result;
        if (x.isNeg != y.isNeg) {
            y.isNeg = !y.isNeg;
            result = RSAUtils.biAdd(x, y);
            y.isNeg = !y.isNeg;
        } else {
            result = new BigInt();
            var n, c;
            c = 0;
            for (var i = 0; i < x.digits.length; ++i) {
                n = x.digits[i] - y.digits[i] + c;
                result.digits[i] = n % biRadix;
                // Stupid non-conforming modulus operation.
                if (result.digits[i] < 0) result.digits[i] += biRadix;
                c = 0 - Number(n < 0);
            }
            // Fix up the negative sign, if any.
            if (c == -1) {
                c = 0;
                for (var i = 0; i < x.digits.length; ++i) {
                    n = 0 - result.digits[i] + c;
                    result.digits[i] = n % biRadix;
                    // Stupid non-conforming modulus operation.
                    if (result.digits[i] < 0) result.digits[i] += biRadix;
                    c = 0 - Number(n < 0);
                }
                // Result is opposite sign of arguments.
                result.isNeg = !x.isNeg;
            } else {
                // Result is same sign.
                result.isNeg = x.isNeg;
            }
        }
        return result;
    };
    
    RSAUtils.biHighIndex = function(x) {
        var result = x.digits.length - 1;
        while (result > 0 && x.digits[result] == 0) --result;
        return result;
    };
    
    RSAUtils.biNumBits = function(x) {
        var n = RSAUtils.biHighIndex(x);
        var d = x.digits[n];
        var m = (n + 1) * bitsPerDigit;
        var result;
        for (result = m; result > m - bitsPerDigit; --result) {
            if ((d & 0x8000) != 0) break;
            d <<= 1;
        }
        return result;
    };
    
    RSAUtils.biMultiply = function(x, y) {
        var result = new BigInt();
        var c;
        var n = RSAUtils.biHighIndex(x);
        var t = RSAUtils.biHighIndex(y);
        var u, uv, k;
    
        for (var i = 0; i <= t; ++i) {
            c = 0;
            k = i;
            for (j = 0; j <= n; ++j, ++k) {
                uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
                result.digits[k] = uv & maxDigitVal;
                c = uv >>> biRadixBits;
                //c = Math.floor(uv / biRadix);
            }
            result.digits[i + n + 1] = c;
        }
        // Someone give me a logical xor, please.
        result.isNeg = x.isNeg != y.isNeg;
        return result;
    };
    
    RSAUtils.biMultiplyDigit = function(x, y) {
        var n, c, uv;
    
        result = new BigInt();
        n = RSAUtils.biHighIndex(x);
        c = 0;
        for (var j = 0; j <= n; ++j) {
            uv = result.digits[j] + x.digits[j] * y + c;
            result.digits[j] = uv & maxDigitVal;
            c = uv >>> biRadixBits;
            //c = Math.floor(uv / biRadix);
        }
        result.digits[1 + n] = c;
        return result;
    };
    
    RSAUtils.arrayCopy = function(src, srcStart, dest, destStart, n) {
        var m = Math.min(srcStart + n, src.length);
        for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
            dest[j] = src[i];
        }
    };
    
    var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
            0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
            0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF];
    
    RSAUtils.biShiftLeft = function(x, n) {
        var digitCount = Math.floor(n / bitsPerDigit);
        var result = new BigInt();
        RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount,
                  result.digits.length - digitCount);
        var bits = n % bitsPerDigit;
        var rightBits = bitsPerDigit - bits;
        for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
            result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
                               ((result.digits[i1] & highBitMasks[bits]) >>>
                                (rightBits));
        }
        result.digits[0] = ((result.digits[i] << bits) & maxDigitVal);
        result.isNeg = x.isNeg;
        return result;
    };
    
    var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
            0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
            0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF];
    
    RSAUtils.biShiftRight = function(x, n) {
        var digitCount = Math.floor(n / bitsPerDigit);
        var result = new BigInt();
        RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0,
                  x.digits.length - digitCount);
        var bits = n % bitsPerDigit;
        var leftBits = bitsPerDigit - bits;
        for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
            result.digits[i] = (result.digits[i] >>> bits) |
                               ((result.digits[i1] & lowBitMasks[bits]) << leftBits);
        }
        result.digits[result.digits.length - 1] >>>= bits;
        result.isNeg = x.isNeg;
        return result;
    };
    
    RSAUtils.biMultiplyByRadixPower = function(x, n) {
        var result = new BigInt();
        RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n);
        return result;
    };
    
    RSAUtils.biDivideByRadixPower = function(x, n) {
        var result = new BigInt();
        RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n);
        return result;
    };
    
    RSAUtils.biModuloByRadixPower = function(x, n) {
        var result = new BigInt();
        RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n);
        return result;
    };
    
    RSAUtils.biCompare = function(x, y) {
        if (x.isNeg != y.isNeg) {
            return 1 - 2 * Number(x.isNeg);
        }
        for (var i = x.digits.length - 1; i >= 0; --i) {
            if (x.digits[i] != y.digits[i]) {
                if (x.isNeg) {
                    return 1 - 2 * Number(x.digits[i] > y.digits[i]);
                } else {
                    return 1 - 2 * Number(x.digits[i] < y.digits[i]);
                }
            }
        }
        return 0;
    };
    
    RSAUtils.biDivideModulo = function(x, y) {
        var nb = RSAUtils.biNumBits(x);
        var tb = RSAUtils.biNumBits(y);
        var origYIsNeg = y.isNeg;
        var q, r;
        if (nb < tb) {
            // |x| < |y|
            if (x.isNeg) {
                q = RSAUtils.biCopy(bigOne);
                q.isNeg = !y.isNeg;
                x.isNeg = false;
                y.isNeg = false;
                r = biSubtract(y, x);
                // Restore signs, 'cause they're references.
                x.isNeg = true;
                y.isNeg = origYIsNeg;
            } else {
                q = new BigInt();
                r = RSAUtils.biCopy(x);
            }
            return [q, r];
        }
    
        q = new BigInt();
        r = x;
    
        // Normalize Y.
        var t = Math.ceil(tb / bitsPerDigit) - 1;
        var lambda = 0;
        while (y.digits[t] < biHalfRadix) {
            y = RSAUtils.biShiftLeft(y, 1);
            ++lambda;
            ++tb;
            t = Math.ceil(tb / bitsPerDigit) - 1;
        }
        // Shift r over to keep the quotient constant. We'll shift the
        // remainder back at the end.
        r = RSAUtils.biShiftLeft(r, lambda);
        nb += lambda; // Update the bit count for x.
        var n = Math.ceil(nb / bitsPerDigit) - 1;
    
        var b = RSAUtils.biMultiplyByRadixPower(y, n - t);
        while (RSAUtils.biCompare(r, b) != -1) {
            ++q.digits[n - t];
            r = RSAUtils.biSubtract(r, b);
        }
        for (var i = n; i > t; --i) {
        var ri = (i >= r.digits.length) ? 0 : r.digits[i];
        var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1];
        var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2];
        var yt = (t >= y.digits.length) ? 0 : y.digits[t];
        var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1];
            if (ri == yt) {
                q.digits[i - t - 1] = maxDigitVal;
            } else {
                q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt);
            }
    
            var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1);
            var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2);
            while (c1 > c2) {
                --q.digits[i - t - 1];
                c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1);
                c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2);
            }
    
            b = RSAUtils.biMultiplyByRadixPower(y, i - t - 1);
            r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i - t - 1]));
            if (r.isNeg) {
                r = RSAUtils.biAdd(r, b);
                --q.digits[i - t - 1];
            }
        }
        r = RSAUtils.biShiftRight(r, lambda);
        // Fiddle with the signs and stuff to make sure that 0 <= r < y.
        q.isNeg = x.isNeg != origYIsNeg;
        if (x.isNeg) {
            if (origYIsNeg) {
                q = RSAUtils.biAdd(q, bigOne);
            } else {
                q = RSAUtils.biSubtract(q, bigOne);
            }
            y = RSAUtils.biShiftRight(y, lambda);
            r = RSAUtils.biSubtract(y, r);
        }
        // Check for the unbelievably stupid degenerate case of r == -0.
        if (r.digits[0] == 0 && RSAUtils.biHighIndex(r) == 0) r.isNeg = false;
    
        return [q, r];
    };
    
    RSAUtils.biDivide = function(x, y) {
        return RSAUtils.biDivideModulo(x, y)[0];
    };
    
    RSAUtils.biModulo = function(x, y) {
        return RSAUtils.biDivideModulo(x, y)[1];
    };
    
    RSAUtils.biMultiplyMod = function(x, y, m) {
        return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m);
    };
    
    RSAUtils.biPow = function(x, y) {
        var result = bigOne;
        var a = x;
        while (true) {
            if ((y & 1) != 0) result = RSAUtils.biMultiply(result, a);
            y >>= 1;
            if (y == 0) break;
            a = RSAUtils.biMultiply(a, a);
        }
        return result;
    };
    
    RSAUtils.biPowMod = function(x, y, m) {
        var result = bigOne;
        var a = x;
        var k = y;
        while (true) {
            if ((k.digits[0] & 1) != 0) result = RSAUtils.biMultiplyMod(result, a, m);
            k = RSAUtils.biShiftRight(k, 1);
            if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break;
            a = RSAUtils.biMultiplyMod(a, a, m);
        }
        return result;
    };
    
    
    $w.BarrettMu = function(m) {
        this.modulus = RSAUtils.biCopy(m);
        this.k = RSAUtils.biHighIndex(this.modulus) + 1;
        var b2k = new BigInt();
        b2k.digits[2 * this.k] = 1; // b2k = b^(2k)
        this.mu = RSAUtils.biDivide(b2k, this.modulus);
        this.bkplus1 = new BigInt();
        this.bkplus1.digits[this.k + 1] = 1; // bkplus1 = b^(k+1)
        this.modulo = BarrettMu_modulo;
        this.multiplyMod = BarrettMu_multiplyMod;
        this.powMod = BarrettMu_powMod;
    };
    
    function BarrettMu_modulo(x) {
        var $dmath = RSAUtils;
        var q1 = $dmath.biDivideByRadixPower(x, this.k - 1);
        var q2 = $dmath.biMultiply(q1, this.mu);
        var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1);
        var r1 = $dmath.biModuloByRadixPower(x, this.k + 1);
        var r2term = $dmath.biMultiply(q3, this.modulus);
        var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1);
        var r = $dmath.biSubtract(r1, r2);
        if (r.isNeg) {
            r = $dmath.biAdd(r, this.bkplus1);
        }
        var rgtem = $dmath.biCompare(r, this.modulus) >= 0;
        while (rgtem) {
            r = $dmath.biSubtract(r, this.modulus);
            rgtem = $dmath.biCompare(r, this.modulus) >= 0;
        }
        return r;
    }
    
    function BarrettMu_multiplyMod(x, y) {
        /*
        x = this.modulo(x);
        y = this.modulo(y);
        */
        var xy = RSAUtils.biMultiply(x, y);
        return this.modulo(xy);
    }
    
    function BarrettMu_powMod(x, y) {
        var result = new BigInt();
        result.digits[0] = 1;
        var a = x;
        var k = y;
        while (true) {
            if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a);
            k = RSAUtils.biShiftRight(k, 1);
            if (k.digits[0] == 0 && RSAUtils.biHighIndex(k) == 0) break;
            a = this.multiplyMod(a, a);
        }
        return result;
    }
    
    var RSAKeyPair = function(encryptionExponent, decryptionExponent, modulus) {
        var $dmath = RSAUtils;
        this.e = $dmath.biFromHex(encryptionExponent);
        this.d = $dmath.biFromHex(decryptionExponent);
        this.m = $dmath.biFromHex(modulus);
        // We can do two bytes per digit, so
        // chunkSize = 2 * (number of digits in modulus - 1).
        // Since biHighIndex returns the high index, not the number of digits, 1 has
        // already been subtracted.
        this.chunkSize = 2 * $dmath.biHighIndex(this.m);
        this.radix = 16;
        this.barrett = new $w.BarrettMu(this.m);
    };
    
    RSAUtils.getKeyPair = function(encryptionExponent, decryptionExponent, modulus) {
        return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus);
    };
    
    if(typeof $w.twoDigit === 'undefined') {
        $w.twoDigit = function(n) {
            return (n < 10 ? "0" : "") + String(n);
        };
    }
    
    RSAUtils.encryptedString = function(key, s) {
        var a = [];
        var sl = s.length;
        var i = 0;
        while (i < sl) {
            a[i] = s.charCodeAt(i);
            i++;
        }
    
        while (a.length % key.chunkSize != 0) {
            a[i++] = 0;
        }
    
        var al = a.length;
        var result = "";
        var j, k, block;
        for (i = 0; i < al; i += key.chunkSize) {
            block = new BigInt();
            j = 0;
            for (k = i; k < i + key.chunkSize; ++j) {
                block.digits[j] = a[k++];
                block.digits[j] += a[k++] << 8;
            }
            var crypt = key.barrett.powMod(block, key.e);
            var text = key.radix == 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix);
            result += text + " ";
        }
        return result.substring(0, result.length - 1); // Remove last space.
    };
    
    RSAUtils.decryptedString = function(key, s) {
        var blocks = s.split(" ");
        var result = "";
        var i, j, block;
        for (i = 0; i < blocks.length; ++i) {
            var bi;
            if (key.radix == 16) {
                bi = RSAUtils.biFromHex(blocks[i]);
            }
            else {
                bi = RSAUtils.biFromString(blocks[i], key.radix);
            }
            block = key.barrett.powMod(bi, key.d);
            for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) {
                result += String.fromCharCode(block.digits[j] & 255,
                                              block.digits[j] >> 8);
            }
        }
        // Remove trailing null, if any.
        if (result.charCodeAt(result.length - 1) == 0) {
            result = result.substring(0, result.length - 1);
        }
        return result;
    };
    
    RSAUtils.setMaxDigits(130);
    
    })(window);

    附件sha1.js

    /*
     * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
     * in FIPS PUB 180-1
     * Version 2.1a Copyright Paul Johnston 2000 - 2002.
     * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
     * Distributed under the BSD License
     * See http://pajhome.org.uk/crypt/md5 for details.
     */
    
    /*
     * Configurable variables. You may need to tweak these to be compatible with
     * the server-side, but the defaults work in most cases.
     */
    var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
    var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
    var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
    
    /*
     * These are the functions you'll usually want to call
     * They take string arguments and return either hex or base-64 encoded strings
     */
    function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
    function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
    function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
    function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
    function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
    function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
    
    /*
     * Perform a simple self-test to see if the VM is working
     */
    function sha1_vm_test()
    {
        return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
    }
    
    /*
     * Calculate the SHA-1 of an array of big-endian words, and a bit length
     */
    function core_sha1(x, len)
    {
        /* append padding */
        x[len >> 5] |= 0x80 << (24 - len % 32);
        x[((len + 64 >> 9) << 4) + 15] = len;
    
        var w = Array(80);
        var a =  1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d =  271733878;
        var e = -1009589776;
    
        for(var i = 0; i < x.length; i += 16)
        {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;
            var olde = e;
    
            for(var j = 0; j < 80; j++)
            {
                if(j < 16) w[j] = x[i + j];
                else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
                var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                    safe_add(safe_add(e, w[j]), sha1_kt(j)));
                e = d;
                d = c;
                c = rol(b, 30);
                b = a;
                a = t;
            }
    
            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
            e = safe_add(e, olde);
        }
        return Array(a, b, c, d, e);
    
    }
    
    /*
     * Perform the appropriate triplet combination function for the current
     * iteration
     */
    function sha1_ft(t, b, c, d)
    {
        if(t < 20) return (b & c) | ((~b) & d);
        if(t < 40) return b ^ c ^ d;
        if(t < 60) return (b & c) | (b & d) | (c & d);
        return b ^ c ^ d;
    }
    
    /*
     * Determine the appropriate additive constant for the current iteration
     */
    function sha1_kt(t)
    {
        return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
            (t < 60) ? -1894007588 : -899497514;
    }
    
    /*
     * Calculate the HMAC-SHA1 of a key and some data
     */
    function core_hmac_sha1(key, data)
    {
        var bkey = str2binb(key);
        if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
    
        var ipad = Array(16), opad = Array(16);
        for(var i = 0; i < 16; i++)
        {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5C5C5C5C;
        }
    
        var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
        return core_sha1(opad.concat(hash), 512 + 160);
    }
    
    /*
     * Add integers, wrapping at 2^32. This uses 16-bit operations internally
     * to work around bugs in some JS interpreters.
     */
    function safe_add(x, y)
    {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 0xFFFF);
    }
    
    /*
     * Bitwise rotate a 32-bit number to the left.
     */
    function rol(num, cnt)
    {
        return (num << cnt) | (num >>> (32 - cnt));
    }
    
    /*
     * Convert an 8-bit or 16-bit string to an array of big-endian words
     * In 8-bit function, characters >255 have their hi-byte silently ignored.
     */
    function str2binb(str)
    {
        var bin = Array();
        var mask = (1 << chrsz) - 1;
        for(var i = 0; i < str.length * chrsz; i += chrsz)
            bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
        return bin;
    }
    
    /*
     * Convert an array of big-endian words to a string
     */
    function binb2str(bin)
    {
        var str = "";
        var mask = (1 << chrsz) - 1;
        for(var i = 0; i < bin.length * 32; i += chrsz)
            str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
        return str;
    }
    
    /*
     * Convert an array of big-endian words to a hex string.
     */
    function binb2hex(binarray)
    {
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var str = "";
        for(var i = 0; i < binarray.length * 4; i++)
        {
            str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
                hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
        }
        return str;
    }
    
    /*
     * Convert an array of big-endian words to a base-64 string
     */
    function binb2b64(binarray)
    {
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var str = "";
        for(var i = 0; i < binarray.length * 4; i += 3)
        {
            var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
            for(var j = 0; j < 4; j++)
            {
                if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
                else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
            }
        }
        return str;
    }
  • 相关阅读:
    Partition4:增加分区
    Partition5:Partiton Scheme是否指定Next Used?
    UniqueIdentifier 数据类型 和 GUID 生成函数
    SQL Server 并发控制 第三篇:隔离级别和行版本(2)
    SQL Server 常用内置函数
    In-Memory:在内存中创建临时表和表变量
    Partition2:对现有表分区
    Partition1:新建分区表
    Partition3:分区切换(Switch)
    Pivot 和 Unpivot
  • 原文地址:https://www.cnblogs.com/loong-hon/p/11430553.html
Copyright © 2011-2022 走看看