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       */

    测试结果截图说明

    服务器:

      客户端:

  • 相关阅读:
    AxInterop.VPIClient DLL注册
    多个事务同时操作数据库
    aspx小试
    WPF 或得PNG图片的外形Path的Data
    Spass导出数据
    Excel VBA小试
    合并Excel文件
    asp.net 中文编码问题
    Delphi中的容器类(3)
    Delphi中的容器类(1)
  • 原文地址:https://www.cnblogs.com/zjp8023/p/15754842.html
Copyright © 2011-2022 走看看