zoukankan      html  css  js  c++  java
  • 前后端java+vue 实现rsa 加解密与摘要签名算法

    RSA 加密、解密、签名、验签、摘要,前后端java+vue联调测试通过

    直接上代码

    // 注意:加密密文与签名都是唯一的,不会变化。
    // 注意:vue 端密钥都要带pem格式。java 不要带pem格式
    // 注意:vue端及java端函数参数、返回值要求是什么类型及何进制。搞明白哪里用base64,哪里2进制,哪里16进制。
    // 重点还是要了解点原理,比如sha1withrsa,先经过sha1算法,知道aaa,哈希后的密文16进制是:7e240de74fb1ed08fa08d38063f6a6a91462a815,对比自己的程序有没有算错。
    // 利用一些在线测试工具帮忙验证自己的程序过程。http://www.metools.info/code/c82.html ; 同时知道如何查引入的类库各api的官网,了解如何使用各函数。
    // 不然遇到莫名奇妙的错误无从解决。报错的地方不一定是程序实际错误的地方。了解查错的方式有:打庄、debug.

    服务器端java:

    工具类,rsa加解密,RsaUtil.java

      1 package com.ruoyi.common.utils.enDeCrypt;
      2 
      3 import com.ruoyi.common.core.text.Convert;
      4 import com.ruoyi.common.exception.UtilException;
      5 
      6 import java.io.ByteArrayOutputStream;
      7 import java.io.UnsupportedEncodingException;
      8 import java.security.*;
      9 import java.util.Base64;
     10 import javax.crypto.Cipher;
     11 import java.security.interfaces.RSAPrivateKey;
     12 import java.security.interfaces.RSAPublicKey;
     13 import java.security.spec.PKCS8EncodedKeySpec;
     14 import java.security.spec.X509EncodedKeySpec;
     15 import java.util.HashMap;
     16 import java.util.Map;
     17 
     18 import static io.netty.util.CharsetUtil.UTF_8;
     19 
     20 
     21 /** 加密和解密花费时间长、速度慢,故使用RSA只能加密少量数据,大量的数据加密还要靠对称密码算法。
     22  * 第一种用法是公钥加密、私钥解密——用于加密;第二种是私钥签名、公钥验签——用于签名
     23  * @author EvianZou
     24  */
     25 public class RsaUtil {
     26 
     27     /**
     28      * 密钥长度与原文长度对应,越长速度越慢
     29      * 1024bit 密钥 能加密明文最大的长度是 1024/8 -11 = 117 byte
     30      * 2048bit 密钥 能加密明文最大的长度是 2048/8 -11 = 245 byte
     31      */
     32     private final static int KEY_SIZE = 1024;
     33     /*
     34      * RSA算法 RSA-1024位 RSA2-2048位
     35      */
     36     private final static String ALGORITHM = "RSA";
     37     //java默认"RSA"="RSA/ECB/PKCS1Padding"
     38     private final static String PADDING_MODE = "RSA";
     39 
     40     /*
     41      * 签名算法
     42      * RSA: 常用 SHA1WithRSA,有 MD2withRSA、MD5withRSA、SHA1withRSA;
     43      * RSA2:  常用:SHA256WithRSA,有 SHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA 、RIPEMD128withRSA、RIPEMD160withRSA;
     44      */
     45     public static final String SIGN_ALGORITHM = "SHA1withRSA";
     46 
     47     /*
     48      * 字符编码
     49      */
     50     private final static String ENCODING = "UTF-8";
     51 
     52     /*
     53      * RSA最大加密明文大小
     54      * RSA:117
     55      * RSA2:245
     56      */
     57     private static final int MAX_ENCRYPT_BLOCK = 117;
     58 
     59     /*
     60      * RSA最大解密密文大小
     61      * RSA:128
     62      * RSA2:256
     63      */
     64     private static final int MAX_DECRYPT_BLOCK = 128;
     65 
     66     public Map<String, String> getKeyMap() {
     67         return keyMap;
     68     }
     69 
     70     public void setKeyMap(Map<String, String> keyMap) {
     71         this.keyMap = keyMap;
     72     }
     73 
     74     /**
     75      * 用于封装随机产生的公钥与私钥
     76      */
     77     private Map<String, String> keyMap;
     78 
     79 
     80     public RsaUtil(boolean isKeyBase64) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchProviderException {
     81         setKeyMap(generateKeyPair(isKeyBase64));
     82     }
     83 
     84     /**
     85      * 随机生成密钥对
     86       * @param isKeyBase64 密钥base64加密为true,hex为false
     87      */
     88     private Map<String, String> generateKeyPair(boolean isKeyBase64) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchProviderException {
     89         // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
     90         KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
     91         // 初始化密钥对生成器
     92         keyPairGen.initialize(KEY_SIZE, new SecureRandom());
     93         // 生成一个密钥对,保存在keyPair中
     94         KeyPair keyPair = keyPairGen.generateKeyPair();
     95         // 得到私钥
     96         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
     97         // 得到公钥
     98         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
     99         String publicKeyString = isKeyBase64 ? Base64.getEncoder().encodeToString(publicKey.getEncoded()) : Convert.bytesToHex(publicKey.getEncoded());
    100 
    101         // 得到私钥字符串
    102         String privateKeyString = isKeyBase64 ? Base64.getEncoder().encodeToString(privateKey.getEncoded()) : Convert.bytesToHex(privateKey.getEncoded());
    103         // 将公钥和私钥保存到Map
    104         Map<String, String> map = new HashMap<>(32);
    105         //表示公钥
    106         map.put("publicKey", publicKeyString);
    107         //表示私钥
    108         map.put("privateKey", privateKeyString);
    109 
    110         return map;
    111     }
    112 
    113     /**
    114      * 流程1:RSA公钥加密,再BASE64加密,再base64解密,再RSA私钥解密
    115      * 流程2:RSA私钥加密,再BASE64加密,再base64解密,再RSA公钥解密
    116      *
    117      * @param text        加密字符串/解密字符串
    118      * @param secretKey   加密秘钥
    119      * @param isPublicKey 公钥/私钥
    120      * @param isEncrypt   加密/解密
    121      * @param isKeyBase64 密钥base64加密为true,hex为false
    122      * @param isTextBase64 密文base64加密为true,hex为false
    123      * @param isUrlCode 密文urlencode为true,否则为false
    124      * @return 密文/明文
    125      * @throws Exception 加密过程中的异常信息
    126      */
    127     private String enDecrypt(String text, String secretKey, boolean isPublicKey, boolean isEncrypt, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {
    128         //base64编码的秘钥
    129         byte[] decodedKey = isKeyBase64 ? Base64.getDecoder().decode(secretKey.getBytes(ENCODING)) : Convert.hexToByteArray(secretKey);
    130         byte[] decodeText;
    131         int encodeMode = 0;
    132         int max_block = 0;
    133         int textLength = 0;
    134         Cipher cipher = Cipher.getInstance(PADDING_MODE);
    135         UrlCode urlCode = new UrlCode();
    136 
    137 
    138         if (isEncrypt) {
    139             encodeMode = Cipher.ENCRYPT_MODE;
    140             max_block = MAX_ENCRYPT_BLOCK;
    141             //待加密字符串
    142             decodeText = text.getBytes(ENCODING);
    143             textLength = text.getBytes(ENCODING).length;
    144         } else {
    145             encodeMode = Cipher.DECRYPT_MODE;
    146             max_block = MAX_DECRYPT_BLOCK;
    147             decodeText = isUrlCode ? urlCode.decodeURL(text, UTF_8).getBytes(ENCODING) : text.getBytes(ENCODING);
    148             // 注意:byte[]转String,不能 byte[].toString(); 可用new String(byte[])
    149             decodeText = isTextBase64 ? Base64.getDecoder().decode(decodeText) : Convert.hexToByteArray(new String(decodeText, ENCODING));
    150             textLength = decodeText.length;
    151         }
    152 
    153         if (isPublicKey) {
    154             cipher.init(encodeMode, (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(decodedKey)));
    155         } else {
    156             cipher.init(encodeMode, (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(decodedKey)));
    157         }
    158 
    159         ByteArrayOutputStream out = new ByteArrayOutputStream();
    160         int offSet = 0;
    161         byte[] cache;
    162         int i = 0;
    163         // 对数据分段加密
    164         while (textLength - offSet > 0) {
    165             if (textLength - offSet > max_block) {
    166                 cache = cipher.doFinal(decodeText, offSet, max_block);
    167             } else {
    168                 cache = cipher.doFinal(decodeText, offSet, textLength - offSet);
    169             }
    170             out.write(cache, 0, cache.length);
    171             i++;
    172             offSet = i * max_block;
    173         }
    174         byte[] byteText = out.toByteArray();
    175         out.close();
    176 
    177         String resultText = out.toString();
    178         if (isEncrypt) {
    179             resultText = isTextBase64 ? Base64.getEncoder().encodeToString(byteText) : Convert.bytesToHex(byteText);
    180             resultText = isUrlCode ? urlCode.encodeURL(resultText, UTF_8) : resultText;
    181         }
    182 
    183         return resultText;
    184     }
    185     
    186     public String encryptByPublicKey(String plainText, String publicKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {
    187         return enDecrypt(plainText, publicKey, true, true, isKeyBase64, isTextBase64, isUrlCode);
    188     }
    189 
    190     public String decryptByPrivateKey(String cipherText, String privateKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {
    191         return enDecrypt(cipherText, privateKey, false, false, isKeyBase64, isTextBase64, isUrlCode);
    192     }
    193     
    194     /**
    195      * RSA签名
    196      *
    197      * @param signText   待签名数据
    198      * @param privateKey 私钥
    199      * @param isKeyBase64 密钥base64加密为true,hex为false
    200      * @param isTextBase64 密文base64加密为true,hex为false
    201      * @param isUrlCode 密文urlencode为true,否则为false
    202      * @return 签名值
    203      */
    204     public String signByPrivateKey(String signText, String privateKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {
    205         try {
    206             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    207             byte[] decodeKey = isKeyBase64 ? Base64.getDecoder().decode(privateKey) : Convert.hexToByteArray(privateKey);
    208 
    209             PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decodeKey);
    210             //DER input, Integer tag error ,原因密钥错误
    211             PrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
    212             Signature signature = Signature.getInstance(SIGN_ALGORITHM);
    213             signature.initSign(private_key);
    214 
    215             String  sign_text = isTextBase64?Convert.bytesToHexString(Base64.getDecoder().decode(signText.getBytes(ENCODING))):signText;
    216            //  System.out.println("服务器端:待签名数据:"+sign_text);
    217 
    218             assert sign_text != null;
    219             byte[] digestText = genDigest(sign_text,SIGN_ALGORITHM );
    220 
    221             // 生成消息摘要 因客户端签名时参数为16进制, 可以通过加密算法验证是否正确
    222             signature.update(Convert.bytesToHexString(digestText).getBytes(ENCODING));
    223             // System.out.println("服务器端:摘要数据:"+new String(digestText));
    224 
    225             byte[] signedByte = signature.sign();
    226             // System.out.println("服务器端:签名数据:"+Convert.bytesToHexString(signedByte));
    227 
    228             UrlCode urlCode = new UrlCode();
    229 
    230             String signedText = isTextBase64 ? Base64.getEncoder().encodeToString(signedByte) : Convert.bytesToHex(signedByte);
    231             signedText = isUrlCode ? urlCode.encodeURL(signedText, UTF_8) : signedText;
    232 
    233             return signedText;
    234 
    235         } catch (Exception e) {
    236             throw new UtilException(e.getMessage());
    237         }
    238     }
    239 
    240 
    241     /*
    242      * 生成消息摘要
    243      */
    244     public byte[] genDigest(String plainText, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    245 
    246         MessageDigest messageDigest = MessageDigest.getInstance(algorithm.split("w")[0]);
    247       //  System.out.println("服务器端,哈希算法:"+algorithm.split("w")[0]);
    248         byte []  digestText = messageDigest.digest(plainText.getBytes(ENCODING));
    249        // System.out.println("服务器端,摘要:"+bytesToHexString(digestText));
    250         return digestText;
    251     }
    252 
    253     /**
    254      * RSA验签名检查
    255      *
    256      * @param signText   待签名数据
    257      * @param signedText 已签名数据
    258      * @param publicKey  公钥
    259      * @param isKeyBase64 密钥base64加密为true,hex为false
    260      * @param isTextBase64 密文base64加密为true,hex为false
    261      * @param isUrlCode 密文urlencode为true,否则为false
    262      * @return 布尔值
    263      */
    264     public boolean verifySignPublicKey(String signText, String signedText, String publicKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {
    265         boolean isVerified;
    266         try {
    267             KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
    268             byte[] decodedKey = isKeyBase64 ? Base64.getDecoder().decode(publicKey) : Convert.hexToByteArray(publicKey);
    269             PublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
    270             Signature signature = Signature.getInstance(SIGN_ALGORITHM);
    271 
    272             signature.initVerify(pubKey);
    273 
    274             signText = isTextBase64?Convert.bytesToHexString( Base64.getDecoder().decode(signText.getBytes(ENCODING))) :signText;
    275             // 生成消息摘要
    276             assert signText != null;
    277            // System.out.println("验证,待签名数据:"+signText);
    278 
    279             byte[] digestText = genDigest(signText,SIGN_ALGORITHM );
    280             // 生成消息摘要
    281             signature.update(Convert.bytesToHexString(digestText).getBytes(ENCODING));
    282 
    283             UrlCode urlCode = new UrlCode();
    284             String decodeText = isUrlCode ? urlCode.decodeURL(signedText, UTF_8) : signedText;
    285             byte[] bytesText = isTextBase64 ? Base64.getDecoder().decode(decodeText) : Convert.hexToByteArray(decodeText);
    286 
    287             //DER input, Integer tag error ,或 DerInputStream.getLength(): lengthTag=111, too big.原因密钥错误
    288             isVerified = signature.verify(bytesText);
    289 
    290         } catch (Exception e) {
    291             throw new UtilException(e.getMessage());
    292         }
    293         return isVerified;
    294     }
    295 
    296 
    297     // PKCS#1 与PKCS#8 格式转换
    298     // 带头和尾的密钥,去掉头和尾后,再按指定格式增加头和尾
    299     public Map<String,String> convertKeyFormat(Map<String,String> mapSource,String keyMode)
    300     {
    301         Map<String,String> map = removeHeaderAndBottom(mapSource,keyMode);
    302         map = formatKey (map,keyMode);
    303 
    304         return map;
    305     }
    306 
    307     public Map<String,String>   removeHeaderAndBottom (Map<String,String> mapSource,String keyMode)
    308     {
    309         Map<String,String> map = new HashMap<>();
    310         Map<String,String> mapHeaderAndBottom_publicKey = genKeyHeaderAndBottom(keyMode,false);
    311         Map<String,String> mapHeaderAndBottom_privateKey  = genKeyHeaderAndBottom(keyMode,true);
    312 
    313         String privateKey = mapSource.get("privateKey");
    314         String publicKey =  mapSource.get("publicKey");
    315 
    316         publicKey =  publicKey.replaceAll(mapHeaderAndBottom_publicKey.get("header"),"");
    317         publicKey = publicKey.replaceAll(mapHeaderAndBottom_publicKey.get("bottom"),"");
    318 
    319         privateKey=privateKey.replaceAll(mapHeaderAndBottom_privateKey.get("header"),"");
    320         privateKey= privateKey.replaceAll(mapHeaderAndBottom_privateKey.get("bottom"),"");
    321 
    322         map.put("publicKey",publicKey);
    323         map.put("privateKey",privateKey);
    324 
    325         return map;
    326     }
    327 
    328     // 不带头和尾的密钥,按指定格式增加头和尾
    329     public  Map<String,String> formatKey( Map<String,String> mapSource, String keyMode)
    330     {
    331         Map<String,String> map = new HashMap<>();
    332 
    333         map.put("publicKey", formatKey(mapSource.get("publicKey"),keyMode,false));
    334         map.put("privateKey", formatKey(mapSource.get("privateKey"),keyMode,true));
    335 
    336         return map;
    337     }
    338 
    339     // 格式化key,增加头和尾
    340     private  String formatKey( String  keyBody, String keyMode,boolean isPrivateKey )
    341     {
    342         Map<String,String> map = genKeyHeaderAndBottom(keyMode,isPrivateKey);
    343         String keyHeader = map.get("header");
    344         String keyBottom =map.get("bottom");
    345         String  strKey = keyHeader + "\n";
    346 
    347         int nPrivateKeyLen = keyBody.length();
    348         char[] status = keyBody.toCharArray();
    349         for(int i = 64; i < nPrivateKeyLen; i+=64)
    350         {
    351             if(status[i] != '\n')
    352             {
    353                 status[i]= '\n';
    354             }
    355             i++;
    356         }
    357         strKey += String.valueOf(status);
    358         strKey += "\n";
    359         strKey += keyBottom;
    360         strKey += "\n";
    361 
    362         return strKey;
    363     }
    364 
    365     // 按指定格式生成头和尾
    366     public Map<String,String> genKeyHeaderAndBottom(String keyMode,boolean isPrivateKey)
    367     {
    368         Map<String,String> map = new HashMap<>();
    369         if (keyMode == "PKCS#1") {
    370             if (isPrivateKey) {
    371                 map.put("header", "-----BEGIN RSA PRIVATE KEY-----");
    372             } else {
    373                 map.put("header", "-----BEGIN RSA PUBLIC KEY-----");
    374             }
    375             if (isPrivateKey) {
    376                 map.put("bottom", "-----END RSA PRIVATE KEY-----");
    377             } else {
    378                 map.put("bottom", "-----END RSA PUBLIC KEY-----");
    379             }
    380         }
    381         else if (keyMode == "PKCS#8") {
    382             if (isPrivateKey) {
    383                 map.put("header", "-----BEGIN PRIVATE KEY-----");
    384             } else {
    385                 map.put("header", "-----BEGIN PUBLIC KEY-----");
    386             }
    387             if (isPrivateKey) {
    388                 map.put("bottom", "-----END PRIVATE KEY-----");
    389             } else {
    390                 map.put("bottom", "-----END PUBLIC KEY-----");
    391             }
    392         }
    393         return map;
    394     }
    395 }
    View Code

    测试使用流程方法

     1  public static void testRSAflow() throws Exception {
     2 
     3         // 测试前后端使用流程
     4         // 1、后端生成密钥对,公钥分享给前端,前端获取到服务器给的公钥。
     5         // 2、前端用服务器端给的公钥 及算法:RSA/ECB/PKCS1Padding 加密"xhy 我爱你 中国 依芸Yiyun !!!" 生成加密数据。
     6         // 3、前端然后生成自己的密钥对,用自己的私钥及算法SHA1withRSA生成摘要签名。
     7         // 4、前端把加密数据、自己的公钥与签名一并发给后端。
     8         // 5、后端收到加密数据、签名数据、前端的公钥,先用前端公钥、签名数据、算法SHA1withRSA 验签,验签通过后再用后端的私钥、算法:RSA/ECB/PKCS1Padding  解密数据。
     9         // 注意:密钥与密文全部base64编码
    10 
    11         RsaUtil rsaUtil = new RsaUtil(true);
    12 
    13         String  privateKey_s = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIfKRPRzS0a9Rg1LQizkfIL1ciAMEFs45tl49ERuwIA1kcUrtB1Cjj3bKMLO0Sp7992ECOWVZsE6DZPle3kVYFufIBT4pjR1oJqRs4Z9g5bkwY6p743eGnT1pxri5LNqBdevlKsjqwcfIdOhIqz2BaeM3PT1O52PI9e+U40XEri7AgMBAAECgYAmNYNLqbmP0SiKCxg226AxlXEklWBw2sUSgpdxPhzKtsgqzA5lgVnXC/kfP+TZaIKpgUKjn3OHgZdae2NQAfTXxTcvhNGYSOeJ8VgslQueoJW7ypgQ/IoNy2DeglObAJ3uCgA4F566j6H7IvcllKGmDT/6PUlljxZJpBMfslspgQJBAP19EMRxmV4vYL7o55oR397UEUXn3vO88SPo2gxaPZ/ltzgaHM5R1zALPE1EfPIPqVdGf2hcowr22pC1BG+nlXsCQQCJIq4USfgNmjGwquo5PyksQ9vsYc/OxGBxEqTpVez24eJb7tvoqvbYfpleeEyWgtvzHqnlY24QdONhVVm5zOXBAkAxt7PwM6+3D2fUSe4TA+p60/FHWsEZ4TcSqfsKbTClCfMzp7t6pAamv61mIka3W2cFXShkGbdI0T3xH+/szlu9AkBi3SSgrd7td39hPSaU1MsLBXT0SmO1Te+1NNq8+VxXc+trmZzidPZ2h3ZsG9AjJf4JnM6g9/iuVoZiclS4VVZBAkEAsPkIGRvX4Nj3ljiBjgdJ68JRZC3gK/kXLNeefIeHg6F/4eyg729PlfdD2mvPb8hiszvsT1zvF8gvxGi4lT6B/w==" ;
    14         String  publicKey_s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHykT0c0tGvUYNS0Is5HyC9XIgDBBbOObZePREbsCANZHFK7QdQo492yjCztEqe/fdhAjllWbBOg2T5Xt5FWBbnyAU+KY0daCakbOGfYOW5MGOqe+N3hp09aca4uSzagXXr5SrI6sHHyHToSKs9gWnjNz09TudjyPXvlONFxK4uwIDAQAB";
    15         String  publicKey_c ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQAB";
    16 
    17         // publicKey_s = rsaUtil.getKeyMap().get("publicKey");
    18         // privateKey_s =rsaUtil.getKeyMap().get("privateKey");
    19         System.out.println("<--- 1 --->服务器端生成公钥:" +publicKey_s );
    20         // System.out.println("<--- 1 --->服务器端生成私钥:"+ privateKey_s);
    21         System.out.println("<--- 1 --->服务器端生成私钥,不公开");
    22         System.out.println("<--- 2 --->客户端获取到服务器端给定的公钥:"+ publicKey_s);
    23         System.out.println("<--- 3 --->客户端用此公钥执行加密,加密原始数据:xhy 我爱你 中国 依芸Yiyun !!!");
    24 
    25         // 客户端用服务器端的公钥生成的密文
    26         String cipherText_c ="eCOu/WkaQ8tZHk2u+Y9bh6RKOVMQGsssjnQB5DVlUeDPhjiIybeQSe7JH7fG5FgsucCi6uFwdU7yWzmkJFmMKGnE1pGLReqSaWgecviSTl1P4jjrq84VJvreoeCmcNUCoqxQvmYuMxB/D4rZ+PTuv0B2sQ4Q5fOH6fbqoj3uD5w=";
    27         cipherText_c ="MoYui9R3RZ+OYamuTvwAGWy2u8rllBQpjGzTXzje9aUM/KiD5nt8DYf1wna5a7DkBYpZ0CRVNHtOHiHgmrheBkpLuAXdh58eVn2hFLn0xCXqIRk+yEZSrF8fHJ7EBhE00WcyfqOoAM+uum57DFxtvATcEnFiEdkRb32JWkumdIY=";
    28         System.out.println("<--- 3 --->客户端生成的加密数据:"+cipherText_c);
    29         System.out.println("<--- 4 --->客户端生成自己的公钥:"+ publicKey_c);
    30        // System.out.println("<--- 4 --->客户端生成自己的私钥:"+ privateKey_c);
    31         System.out.println("<--- 4 --->客户端生成自己的私钥,不公开");
    32 
    33         // 客户端利用自己的私钥生成摘要后进行的签名
    34         String  signedText_c = "uFy+PqjxdxusV5+a9VR0cvk1XY0+Th8jWBT581irWVEDyzq00xGphQ8KIyApgvPw5+KP1DB/M7tMfd0viUT4w8i4VcyhGmRlk0XNkuRhQDgcWeZ5XKIoJ1ORQ0ecxcAAAAlPwMe2wCbPClXFmhJzypJtS7nKFzE/oeZg7nr91zg=";
    35         signedText_c ="reCyRzzxeo1i269BdV5TBrYqiYNyWEmk+i6Oxq/0MJz581tThBikh6/Z+hTZ3vY03UngoXwxB7pZBPW7FUxtwdqS8FcKtlVShaz0ZwU22BHbqFBvCvr4C224HQAdNeVoeHb3o8O/DEjNruUzM1NkweLqayI0unieRYxebvCweTE=";
    36         System.out.println("<--- 4 --->客户端利用自己的私钥生成摘要而后签名数据:"+signedText_c);
    37         System.out.println("<--- 5 --->客户端发送数据至服务器端,1自己的公钥,2自己的加密数据,3自己的签名数据");
    38         System.out.println("<--- 6 --->服务器端接收到来自客户端的数据:1客户端的公钥,2客户端的加密数据,3客户端的签名数据");
    39         System.out.println("<--- 6 --->1客户端的公钥:"+publicKey_c);
    40         System.out.println("<--- 6 --->2客户端的加密数据:"+cipherText_c);
    41         System.out.println("<--- 6 --->2客户端的签名数据:"+signedText_c);
    42 
    43         boolean isPassed = rsaUtil.verifySignPublicKey(cipherText_c, signedText_c, publicKey_c, true,true,false);
    44         System.out.println("<--- 7 --->服务器端用自己的公钥进行签名验证,结果:"+isPassed);
    45         if (isPassed)
    46         {
    47             System.out.println("<--- 8 --->服务器端验签成功,开始解密数据...");
    48 
    49             String  plainText = "";
    50             plainText = rsaUtil.decryptByPrivateKey(cipherText_c,privateKey_s,true,true,false);
    51 
    52             System.out.println("<--- 9 --->服务器端解密数据成功:"+ plainText);
    53         }
    54 
    55         /* 测试代码
    56         // 服务器端用服务器端的公钥生成的密文
    57         String cipherText_s ="";
    58         String plainText = "xhy 我爱你 中国 依芸Yiyun !!!";
    59         cipherText_s = rsaUtil.encryptByPublicKey(plainText, publicKey_s,true, true,false);
    60         System.out.println("服务器端执行加密,公钥加密:"+cipherText_s);
    61 
    62         // 服务器端利用客户端的私钥进行签名
    63         String  signedText_s = rsaUtil.signByPrivateKey(cipherText_c, privateKey_c,true, true,false);
    64         System.out.println("服务器端执行签名,私钥签名:"+signedText_s);
    65         */
    66 
    67           /* String  privateKey_c = "MIICXAIBAAKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQABAoGARuvaf7la9ojnwigTtFuO6Fz1PoSe+SHKrysL/GiGGyNyapTjccz+eAcaA5Ek8WO6K7S7nRZpeKzAGsS92aQmt66BpOqI+JJ2uM+K1HzH5K5rQ4rnaC/Hbd+4zsltVzuLbsICDGSlkpTSKK5YdIkA5YPMXoQek4zoYpUnKT2AxEECQQDoDrjIJ4MllIpc" +
    68                 "gAWjahga1YrcTIcQPBwG9rfX7zk2nKFZF5rOB6iDHjE9mo9EOD/s7j3Z5eefwVkp" +
    69                 "hRnbXJp3AkEA5bpMSf8zyBKfMZll3vdtDTDqnsVzOu89RxQYgceyWZ/OcFgvc9hg" +
    70                 "NYoV/EkGQXcHWL1gPQwWpMRfS8L/DjbNIwJBAL3NBL/Y6YB8TOq5X2M4bHzOOiRT" +
    71                 "h4j00Su08ctxA8eyNpnrH5fyVZbgw/+SAioXI9oDRp2JWHinKOk3z11HEaMCQDI/" +
    72                 "qLY60xm9MQMJWaYGmtzayUcHS2glslKcy6t/gbxm3yHluCNvvcOYO6zeUDb7kSjQ" +
    73                 "638O6NkLdwi8U0vJot8CQHEfumEFZ0LYbz914TZOWe2q0UKOUZaHgQIwoJ3n2yxJ" +
    74                 "p7Ps3k9t2Of8Tm+HqZYCkSz8henOM8aFCS2GPD8Pkf4=" ;
    75         */
    76     }
    View Code

    客户端vue:

    工具类,常用加解密算法,enDecrypt.js

      1  /* base64 加解密
      2   */
      3  export let Base64 = require('js-base64').Base64
      4 
      5  /* md5 加解密
      6  */
      7  export let crypto = require('crypto');
      8  export let md5 = require('js-md5');
      9  export let CryptoJS = require('crypto-js');
     10  export let MD5 = CryptoJS.MD5;
     11  /*
     12   *引入jsencrypt实现数据RSA加密
     13   */
     14  import JSEncrypt from 'jsencrypt';
     15  // jsencrypt.js处理长文本数据时报错  Message too long for RSA
     16  // encryptlong是基于jsencrypt扩展的长文本分段加解密功能。
     17  import Encrypt from "encryptlong";
     18  // rsa sign
     19  import jsrsasign from 'jsrsasign'
     20 
     21  // Message Digest algorithm 5,信息摘要算法
     22  // alglorithm:md5、sha1、sha256
     23  export function Md5(plainText, alglorithm, encoding){
     24    const hash =  crypto.createHash(alglorithm)
     25    hash.update(plainText);//加密内容
     26    return  hash.digest(encoding);//密文
     27  }
     28 
     29  //Hash Message Authentication Code,散列消息鉴别码
     30  //Secure Hash Algorithm,安全散列算法
     31  //alglorithm:md5、sha256、sha1
     32  export function HMac(plainText, secretKey,alglorithm, encoding){
     33    const hmac= crypto.createHmac(alglorithm, secretKey);
     34    const cipherText= hmac.update(plainText);//加密内容
     35    return  cipherText.digest(encoding);//密文
     36  }
     37 
     38  // Data Encryption Standard,数据加密算法
     39  // DES/DES3/AES 加密, key与iv长度必须是8的倍数
     40  // mode:CryptoJS.mode.CBC、CryptoJS.mode.ECB、CryptoJS.mode.CFB
     41  // padding:CryptoJS.pad.ZeroPadding、CryptoJS.pad.Pkcs7、CryptoJS.pad.NoPadding
     42  export function encrypt ( algorithm, plainText,key, iv, mode, padding, isTextBase64) {
     43      key = key ? key : "abcdefghijklmnop";
     44      iv = iv ? iv : "0102030405060708";
     45 
     46      const keyHex = CryptoJS.enc.Utf8.parse(key);
     47      const ivHex = CryptoJS.enc.Utf8.parse(iv);
     48      const option = { iv:keyHex,mode: mode, padding: padding }
     49      let encrypted = null  ;
     50      if(algorithm === "TripleDES"){
     51        encrypted = CryptoJS.TripleDES.encrypt(plainText, keyHex, option)
     52      }else if(algorithm === "DES"){
     53        encrypted = CryptoJS.DES.encrypt(plainText, keyHex, option)
     54      }
     55      else if(algorithm === "AES"){
     56        encrypted =  CryptoJS.AES.encrypt(plainText, keyHex, option)
     57      }
     58      return isTextBase64?CryptoJS.enc.Base64.stringify(encrypted.ciphertext):encrypted.ciphertext.toString();
     59  }
     60 
     61  // DES/DES3/AES解密,key与iv长度必须是8的倍数
     62  export function decrypt (algorithm,cipherText,key, iv, mode, padding, isTextBase64) {
     63      key = key ? key : "abcdefghijklmnop";
     64      iv = iv ? iv : "0102030405060708";
     65 
     66      const keyHex = CryptoJS.enc.Utf8.parse(key);
     67      const ivHex = CryptoJS.enc.Utf8.parse(iv);
     68      const decryptText = isTextBase64?  CryptoJS.enc.Base64.parse(cipherText):cipherText;
     69      const textHex = { ciphertext:  isTextBase64?decryptText:CryptoJS.enc.Hex.parse(decryptText) }
     70      const option = { iv:ivHex,mode: mode, padding: padding }
     71      let decrypted = null;
     72      if(algorithm === "TripleDES"){
     73        decrypted = CryptoJS.TripleDES.decrypt(textHex, keyHex, option);
     74      }else if(algorithm === "DES"){
     75        decrypted = CryptoJS.DES.decrypt(textHex, keyHex, option);
     76      }
     77      else if(algorithm === "AES"){
     78        decrypted =  CryptoJS.AES.decrypt(textHex, keyHex, option);
     79      }
     80      return decrypted.toString(CryptoJS.enc.Utf8);
     81  }
     82 
     83  export function stringToHex(strSource) {
     84    if(strSource === "")
     85      return "";
     86    var hexCharCode = [];
     87    for(var i = 0; i < strSource.length; i++) {
     88      hexCharCode.push((strSource.charCodeAt(i)).toString(16));
     89    }
     90    return hexCharCode.join("");
     91  }
     92 
     93  export function hexToString(hexCharCodeStr) {
     94    var trimedStr = hexCharCodeStr.trim();
     95    var len = trimedStr.length;
     96    if(len % 2 !== 0) {
     97      alert("Illegal Format ASCII Code!");
     98      return "";
     99    }
    100    var curCharCode;
    101    var resultStr = [];
    102    for(var i = 0; i < len;i = i + 2) {
    103      curCharCode = parseInt(trimedStr.substr(i, 2), 16); // ASCII Code Value
    104      resultStr.push(String.fromCharCode(curCharCode));
    105    }
    106    return resultStr.join("");
    107  }
    108 
    109  /** RSA 加密过程
    110   * (1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。
    111   * (2)A传递自己的公钥给B,B用A的公钥对消息进行加密。
    112   * (3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。
    113   *  在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性。
    114   *  因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。
    115   *  使用方法
    116   *  客户端初始化访问服务器端时,服务器端会生成一对RSA对,及公钥和密钥。
    117   *  如果前端只需要将要传给后端的数据进行加密后传输,那么前端可以只要公钥,通过公钥对要传输的参数进行加密后把加密的字符串发给后端,后端取出保存的密码种子或者直接保存的私钥,采用私钥对加密字符串进行解密,得到明文。
    118   *  如果前端要获取后端传过来的已经加密后的字符串,并且解密使用,那么前端就需要拿到RSA对立面的私钥进行解密后使用了。
    119   * */
    120  /* JSEncrypt 公钥加密  padding:pkcs1pad2 */
    121  export function RsaJSEncrypt(plainText,publicKey,isKeyBase64,isTextBase64,isURLCode) {
    122    const jsencrypt = new JSEncrypt({
    123      default_key_size: 1024
    124    });
    125    // setPublicKey 参数默认需要base64,如果是十六进制编码则需要转换为base64,jsrsasign.b64tohex,jsrsasign.hextob64
    126    isKeyBase64?jsencrypt.setPublicKey(publicKey):jsencrypt.setPublicKey( jsrsasign.hextob64(publicKey));
    127    // 如果是对象/数组的话,需要先JSON.stringify转换成字符串
    128    // 处理中文乱码,服务器端:String result = java.net.URLDecoder.decode(cipherText ,"UTF-8");
    129    let  cipherText = jsencrypt.encrypt(plainText);
    130 
    131    // 默认加密结果为base64编码
    132    cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);
    133    // +号服务器端不识别,url编码
    134    cipherText = isURLCode? encodeURIComponent(cipherText):cipherText;
    135 
    136    return  cipherText;
    137  }
    138 
    139  /* JSEncrypt 私钥解密 padding:pkcs1pad2 */
    140  export function RsaJSDecrypt(cipherText,privateKey,isKeyBase64,isTextBase64,isURLCode) {
    141    const jsencrypt = new JSEncrypt({
    142      default_key_size: 1024,
    143      padding: crypto.constants.RSA_PKCS1_PADDING
    144    });
    145 
    146    isKeyBase64?jsencrypt.setPrivateKey(privateKey):jsencrypt.setPrivateKey(jsrsasign.hextob64(privateKey));
    147 
    148    cipherText = isURLCode?decodeURIComponent(cipherText):cipherText;
    149    cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);
    150 
    151    return jsencrypt.decrypt(cipherText);
    152  }
    153 
    154  /* 长文本分段加密 */
    155  export function RsaEncrypt(plainText,publicKey,isKeyBase64,isTextBase64,isURLCode) {
    156    const encryptor = new Encrypt({
    157      default_key_size: 1024,
    158      padding: crypto.constants.RSA_PKCS1_PADDING
    159    });
    160    if (isKeyBase64) {
    161      encryptor.setPublicKey(publicKey)
    162    }
    163    else {
    164      encryptor.setPublicKey(jsrsasign.hextob64(publicKey));
    165    }
    166 
    167    // 处理中文乱码,服务器端:String result = java.net.URLDecoder.decode(cipherText ,"UTF-8");
    168 
    169   let cipherText = encryptor.encryptLong(plainText);
    170 
    171     cipherText = isTextBase64?cipherText:jsrsasign.hextob64(cipherText);
    172    // +号服务器端不识别,url编码
    173    cipherText = isURLCode? encodeURIComponent(cipherText):cipherText;
    174 
    175    return  cipherText;
    176  }
    177 
    178  /* 长文本分段解密 */
    179  export function RsaDecrypt(cipherText,privateKey,isKeyBase64,isTextBase64,isURLCode) {
    180    const encryptor = new Encrypt({
    181      default_key_size: 1024,
    182      padding: crypto.constants.RSA_PKCS1_PADDING
    183    })
    184 
    185    if (isKeyBase64){
    186     encryptor.setPrivateKey(privateKey)
    187   }
    188   else{
    189     encryptor.setPrivateKey(jsrsasign.hextob64(privateKey));
    190   }
    191    cipherText = isURLCode?decodeURIComponent(cipherText):cipherText;
    192    cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);
    193 
    194    return encryptor.decryptLong(cipherText);
    195  }
    196 
    197  // 获取签名 privateKey
    198  export function RsaSign(plainText,privateKey,format_key, algorithm,isKeyBase64,isTextBase64,isURLCode)
    199  {
    200    // 生成签名对象
    201    let sign = genSign(isKeyBase64?privateKey:jsrsasign.hextob64(privateKey),format_key, algorithm);
    202     plainText = isTextBase64?jsrsasign.b64tohex(plainText):plainText;
    203   // console.log("待签名前数据:"+plainText);
    204     let plain_Text = genDigest(plainText,algorithm);
    205 
    206    // console.log("待签名摘要数据:"+plain_Text);
    207     sign.updateString(plain_Text);
    208 
    209    // 默认签名数据为十六进制数据
    210     let signedText = isTextBase64?jsrsasign.hextob64(sign.sign()):sign.sign();
    211 
    212    // console.log("生成签名数据:"+sign.sign());
    213    // +号服务器端不识别,url编码
    214     signedText = isURLCode? encodeURIComponent(signedText):signedText;
    215 
    216     return signedText;
    217  }
    218 
    219  // 验证签名 publicKey_s 服务器端的公钥
    220  // alglorithm: SHA1withRSA、MD5withRSA、SHA256withRSA、 SHA384withRSA、SHA512withRSA、RIPEMD160withRSA
    221  // format_key: PKCS#1、PKCS#5、PKCS#8
    222  /*
    223   * PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封。
    224   * PKCS#3:定义Diffie-Hellman密钥交换协议。
    225   * PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息[24]。
    226   * PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。
    227   * PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。
    228   * PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。
    229   * PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型。
    230   * PKCS#10:描述证书请求语法。
    231   * PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备。
    232   * PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。
    233   * PKCS#13:椭圆曲线密码体制标准。
    234   * PKCS#14:伪随机数生成标准。
    235   * PKCS#15:密码令牌信息格式标准。
    236   */
    237  export function RsaVerifySign(plainText,signedText,publicKey,format_key, algorithm,isKeyBase64,isTextBase64,isURLCode)
    238  {
    239    // 生成签名
    240    let verifySign = genSign(isKeyBase64?publicKey:jsrsasign.hextob64(publicKey),format_key, algorithm);
    241    plainText = isTextBase64?jsrsasign.b64tohex(plainText):plainText;
    242    // 根据明文生成摘要
    243    let digestText = genDigest(plainText,algorithm);
    244 
    245    verifySign.updateString(digestText);
    246 
    247    signedText = isURLCode?decodeURIComponent(signedText):signedText;
    248    signedText = isTextBase64?jsrsasign.b64tohex(signedText):signedText;
    249 
    250    return  verifySign.verify(signedText);
    251  }
    252 
    253  // 根据明文生成摘要
    254  //SHA1withRSA、MD5withRSA、SHA256withRSA、 SHA384withRSA、SHA512withRSA、RIPEMD160withRSA
    255  export function genDigest(plainText,algorithm ){
    256    let option = { "alg": algorithm.split('w')[0], "prov":"cryptojs/jsrsa", }
    257   // console.log("算法:"+algorithm.split('w')[0]);
    258    let text = new jsrsasign.KJUR.crypto.MessageDigest(option);   // 摘要
    259    text.updateString(plainText);
    260 
    261    let digestText = text.digest();
    262    // console.log("摘要:"+digestText);
    263    return digestText;
    264  }
    265 
    266  /* 生成rsa签名对象
    267   * */
    268  export function genSign(RsaKey,format_key, algorithm)
    269  {
    270    // 密钥要写开头和结束
    271    // var private_key = '-----BEGIN PRIVATE KEY-----' + privateKey_s + '-----END PRIVATE KEY-----'
    272    // 读取解析pem格式的秘钥, 生成秘钥实例 (RSAKey)
    273    let rsaKey = new jsrsasign.RSAKey();
    274    if (format_key === "PKCS#1" || format_key === "PKCS#5"|| format_key === "PKCS#7"|| format_key === "PKCS#8") {
    275      rsaKey = jsrsasign.KEYUTIL.getKey(RsaKey);
    276      // rsaSign.readPrivateKeyFromPEMString(privateKey_s);
    277    }
    278 
    279    let option= {
    280      "alg":algorithm,
    281      "prov":"cryptojs/jsrsa",
    282      "prvkeypem": rsaKey
    283    };
    284 
    285    let sign = new jsrsasign.KJUR.crypto.Signature(option);
    286    sign.init(rsaKey);
    287 
    288    return sign;
    289  }

    前端使用代码流程:

     1 // 测试前后端使用流程
     2       // 1、后端生成密钥对,公钥分享给前端,前端获取到服务器给的公钥。
     3       // 2、前端用服务器端给的公钥 及算法:RSA/ECB/PKCS1Padding 加密"xhy 我爱你 中国 依芸Yiyun !!!" 生成加密数据。
     4       // 3、前端然后生成自己的密钥对,用自己的私钥及算法SHA1withRSA生成摘要签名。
     5       // 4、前端把加密数据、自己的公钥与签名一并发给后端。
     6       // 5、后端收到加密数据、签名数据、前端的公钥,先用前端公钥、签名数据、算法SHA1withRSA 验签,验签通过后再用后端的私钥、算法:RSA/ECB/PKCS1Padding 解密数据。
     7       // 注意:密钥与密文全部base64编码
     8 
     9       let  plainText = "xhy 我爱你 中国 依芸Yiyun !!!";
    10 
    11       let privateKey_c = "-----BEGIN RSA PRIVATE KEY-----" +
    12         "MIICXAIBAAKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/" +
    13         "o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLl" +
    14         "dKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQAB" +
    15         "AoGARuvaf7la9ojnwigTtFuO6Fz1PoSe+SHKrysL/GiGGyNyapTjccz+eAcaA5Ek" +
    16         "8WO6K7S7nRZpeKzAGsS92aQmt66BpOqI+JJ2uM+K1HzH5K5rQ4rnaC/Hbd+4zslt" +
    17         "VzuLbsICDGSlkpTSKK5YdIkA5YPMXoQek4zoYpUnKT2AxEECQQDoDrjIJ4MllIpc" +
    18         "gAWjahga1YrcTIcQPBwG9rfX7zk2nKFZF5rOB6iDHjE9mo9EOD/s7j3Z5eefwVkp" +
    19         "hRnbXJp3AkEA5bpMSf8zyBKfMZll3vdtDTDqnsVzOu89RxQYgceyWZ/OcFgvc9hg" +
    20         "NYoV/EkGQXcHWL1gPQwWpMRfS8L/DjbNIwJBAL3NBL/Y6YB8TOq5X2M4bHzOOiRT" +
    21         "h4j00Su08ctxA8eyNpnrH5fyVZbgw/+SAioXI9oDRp2JWHinKOk3z11HEaMCQDI/" +
    22         "qLY60xm9MQMJWaYGmtzayUcHS2glslKcy6t/gbxm3yHluCNvvcOYO6zeUDb7kSjQ" +
    23         "638O6NkLdwi8U0vJot8CQHEfumEFZ0LYbz914TZOWe2q0UKOUZaHgQIwoJ3n2yxJ" +
    24         "p7Ps3k9t2Of8Tm+HqZYCkSz8henOM8aFCS2GPD8Pkf4=" +
    25         "-----END RSA PRIVATE KEY-----";
    26 
    27       let publicKey_c ="-----BEGIN PUBLIC KEY-----" +
    28         "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPgskvyi9D/IuD0x73M2UOxBH" +
    29         "3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHv" +
    30         "vVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9i" +
    31         "Fi2KDWwF30e2PHRpRQIDAQAB" +
    32         "-----END PUBLIC KEY-----";
    33 
    34       let publicKey_s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHykT0c0tGvUYNS0Is5HyC9XIgDBBbOObZePREbsCANZHFK7QdQo492yjCztEqe/fdhAjllWbBOg2T5Xt5FWBbnyAU+KY0daCakbOGfYOW5MGOqe+N3hp09aca4uSzagXXr5SrI6sHHyHToSKs9gWnjNz09TudjyPXvlONFxK4uwIDAQAB";
    35 
    36       console.log("<--- 2 --->客户端获取到服务器端给定的公钥:"+ publicKey_s);
    37 
    38       let cipherText_c =this.$RsaEncrypt(plainText,publicKey_s,true,true,false);
    39       console.log("<--- 3 --->客户端利用服务器端的公钥加密数据,生成密文,base64编码输出\n"+cipherText_c);
    40       // 记录 cipherText_c = "eCOu/WkaQ8tZHk2u+Y9bh6RKOVMQGsssjnQB5DVlUeDPhjiIybeQSe7JH7fG5FgsucCi6uFwdU7yWzmkJFmMKGnE1pGLReqSaWgecviSTl1P4jjrq84VJvreoeCmcNUCoqxQvmYuMxB/D4rZ+PTuv0B2sQ4Q5fOH6fbqoj3uD5w=";
    41 
    42      let signedText_c = this.$RsaSign(cipherText_c,privateKey_c,"PKCS#8","SHA1withRSA",true,
    43        true,false);
    44       console.log("<--- 4 --->客户端利用自己生成的私钥签名数据,生成摘要与签名\n"+signedText_c);
    45       console.log("<--- 4 --->客户端生成自己的公钥\n"+publicKey_c);
    46       console.log("<--- 5 --->客户端发送数据至服务器端,1客户端的公钥,2客户端的加密数据,3客户端的签名数据\n");
    47       // 记录 signedText_c = "uFy+PqjxdxusV5+a9VR0cvk1XY0+Th8jWBT581irWVEDyzq00xGphQ8KIyApgvPw5+KP1DB/M7tMfd0viUT4w8i4VcyhGmRlk0XNkuRhQDgcWeZ5XKIoJ1ORQ0ecxcAAAAlPwMe2wCbPClXFmhJzypJtS7nKFzE/oeZg7nr91zg=";
    48       // 注意:加密密文与签名都是唯一的,不会变化。
    49       // 注意:vue 端密钥都要带头。
    50       // 注意:vue端及java端函数参数要求是什么类型及何进制。搞明白哪里用base64,哪里2进制,哪里16进制。
    51       // 重点还是要了解点原理,比如sha1withrsa,先经过sha1算法,知道aaa,哈希后的密文16进制是:7e240de74fb1ed08fa08d38063f6a6a91462a815,对比自己的程序有没有算错。
    52       // 利用一些在线测试工具帮忙验证自己的程序过程。http://www.metools.info/code/c82.html ; 同时知道如何查引入的类库各api的官网,了解如何使用各函数。
    53       // 不然遇到莫名奇妙的错误无从解决。报错的地方不一定是程序实际错误的地方。了解查错的方式有:打庄、debug.
    54 
    55       /* 仅供测试使用,加密数据及验签
    56         let privateKey_s = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIfKRPRzS0a9Rg1LQizkfIL1ciAMEFs45tl49ERuwIA1kcUrtB1Cjj3bKMLO0Sp7992ECOWVZsE6DZPle3kVYFufIBT4pjR1oJqRs4Z9g5bkwY6p743eGnT1pxri5LNqBdevlKsjqwcfIdOhIqz2BaeM3PT1O52PI9e+U40XEri7AgMBAAECgYAmNYNLqbmP0SiKCxg226AxlXEklWBw2sUSgpdxPhzKtsgqzA5lgVnXC/kfP+TZaIKpgUKjn3OHgZdae2NQAfTXxTcvhNGYSOeJ8VgslQueoJW7ypgQ/IoNy2DeglObAJ3uCgA4F566j6H7IvcllKGmDT/6PUlljxZJpBMfslspgQJBAP19EMRxmV4vYL7o55oR397UEUXn3vO88SPo2gxaPZ/ltzgaHM5R1zALPE1EfPIPqVdGf2hcowr22pC1BG+nlXsCQQCJIq4USfgNmjGwquo5PyksQ9vsYc/OxGBxEqTpVez24eJb7tvoqvbYfpleeEyWgtvzHqnlY24QdONhVVm5zOXBAkAxt7PwM6+3D2fUSe4TA+p60/FHWsEZ4TcSqfsKbTClCfMzp7t6pAamv61mIka3W2cFXShkGbdI0T3xH+/szlu9AkBi3SSgrd7td39hPSaU1MsLBXT0SmO1Te+1NNq8+VxXc+trmZzidPZ2h3ZsG9AjJf4JnM6g9/iuVoZiclS4VVZBAkEAsPkIGRvX4Nj3ljiBjgdJ68JRZC3gK/kXLNeefIeHg6F/4eyg729PlfdD2mvPb8hiszvsT1zvF8gvxGi4lT6B/w==" ;
    57 
    58         console.log("RSAVerifySign_pubK="+this.$RsaVerifySign(cipherText_c, signedText_c,
    59         publicKey_c,"PKCS#8","SHA1withRSA",true,true,false));
    60 
    61         plainText = "";
    62         plainText = this.$RsaDecrypt(cipherText_c, privateKey_s,true,true,false)
    63         console.log("RSADe_priK="+plainText);
    64       */

    测试结果截图说明

    服务器:

      客户端:

  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/zjp8023/p/15754842.html
Copyright © 2011-2022 走看看