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;
    }
  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/loong-hon/p/11430553.html
Copyright © 2011-2022 走看看