• 第三章 消息摘要算法MD5SHAMAC


    6.1、MD5

    • 推荐使用CC(即Commons Codec)实现
    • 虽然已被破解,但是仍旧广泛用于注册登录模块与验证下载的文件的完整性
    • 可以自己写一个注册登录模块;自己下载一个MD5加密的文件,然后通过之前编写的工具类(或者使用CC的方法)进行验证(具体的例子在《Java加密与解密艺术(第二版)中有》)

    6.2、SHA

    • 推荐使用CC(即Commons Codec)实现
    • SHA1已被破解,SHA256广泛用于注册登录模块与验证下载的文件的完整性,并且SHA256在spring security中也有用到
    • 可以自己写一个注册登录模块;自己下载一个SHA加密的文件,然后通过之前编写的工具类(或者使用CC的方法)进行验证
    • MD5与SHA常常用于数字证书(这个之后会讲)的签名算法,但是SHA更常用

    6.3、MAC

    • 在MD与SHA系列的算法上增加了密钥,使得安全程度成为三种方法之最

    3.1、消息摘要算法:防止消息在传递过程中被篡改。

    原理:任何消息经过消息摘要算法后,都会产生唯一的散列值(即“数据指纹”)(同一段消息无论经过多少次相同的消息摘要算法加密,结果都相同),所以如果消息在传送过程中被修改,那么算出来的数据指纹也与原本的消息算出来的不同了,如果没有被修改,则数据指纹是相同的。

    特点:单向性(即只有加密,没有解密)

    3.2、MD5(算法已被破解,应用于安全程度要求不高的情况下)

    实现方式:

    • Commons Codec(“CC”,最推荐,因为封装了JDK的底层代码,并且提供了二进制字节数组向十六进制转化的方法)
    • JDK(没有提供二进制字节数组向十六进制转化的方法,想要进行转化,需要借助BC)
    • Bouncy Castle(“BC”,不推荐,实现比较复杂)

    下边只列出基于CC的工具类代码,至于基于JDK的代码可以参考“《Java加密与解密的艺术(第2版)》”,基于BC的代码可参考“慕课网”

    3.2.1、基于CC实现的MD5加密算法

    pom.xml

    1 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
    2 <dependency>
    3     <groupId>commons-codec</groupId>
    4     <artifactId>commons-codec</artifactId>
    5     <version>1.10</version>
    6 </dependency>

    工具类

    1 package com.util.md5;
     2 
     3 import java.io.UnsupportedEncodingException;
     4 import java.security.NoSuchAlgorithmException;
     5 import org.apache.commons.codec.digest.DigestUtils;
     6 /**
     7  * 基于Commons Codec的md5算法
     8  */
     9 public class Md5CC {
    10     private static final String ENCODING = "UTF-8";
    11     
    12     /**
    13      * MD5加密,加密后的结果为二进制字节数组
    14      */
    15     public static byte[] encode(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException {
    16         return DigestUtils.md5(data.getBytes(ENCODING));
    17     }
    18     
    19     /**
    20      *MD5加密,加密后的结果为二进制字节数组,并且在这里将二进制字节数组转为了32位的16进制
    21      */
    22     public static String encodeMd5Hex(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException {
    23         return new String(DigestUtils.md5Hex(data.getBytes(ENCODING)));//这里直接使用new String(encodedByte,"UTF-8")不行
    24     }
    25     
    26     /**
    27      * 测试
    28      * @param args
    29      * @throws UnsupportedEncodingException 
    30      * @throws NoSuchAlgorithmException 
    31      */
    32     public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    33         
    34         String data = "找一个好姑娘做老婆是我的梦 想!";
    35         /*************测试encode()**************/
    36         System.out.println("原文-->"+data);
    37         byte[] encodedByte = Md5CC.encode(data);
    38         System.out.println("加密后-->"+encodedByte);
    39         byte[] encodedByte2 = Md5CC.encode(data);
    40         System.out.println("加密后-->"+encodedByte2);
    41         for(int i=0;i<encodedByte.length;i++){
    42             System.out.println(encodedByte[i]==encodedByte2[i]);
    43         }
    44         /*************测试encodeMd5Hex()**************/
    45         System.out.println("原文-->"+data);
    46         String encodedStr = Md5CC.encodeMd5Hex(data);
    47         System.out.println("加密后-->"+encodedStr);
    48         String encodedStr2 = Md5CC.encodeMd5Hex(data);
    49         System.out.println("加密后-->"+encodedStr2);
    50         System.out.println(encodedStr.equals(encodedStr2));
    51     }
    52 }

    jar包的引入参考第二章的第一个例子进行即可,在测试的过程中,自己去试着看看“同一个消息多次进行MD5加密后结果是不是相同”;

    在encode()方法的测试中判断两个byte[]是否相等:按索引依次比较两个字节数组中的元素是否相同即可(如果使用main方法去测的话);如果使用Junit,直接使用assertArrayEquals(array1,array2)即可。

    4.1、SHA

    原理:消息摘要长度(可以定量为加密后的字符串的长度)越长,安全性越高

    • MD5:128位二进制摘要(32位16进制字符串)(已破解)
    • SHA1:160位二进制摘要(40位16进制字符串)(已破解)
    • SHA256:256位二进制摘要(64位16进制字符串)(常用,在spring security中也有使用到)

    实现方式:

    • Commons Codec(“CC”,最推荐,因为封装了JDK的底层代码,并且提供了二进制字节数组向十六进制转化的方法)
    • JDK(没有提供二进制字节数组向十六进制转化的方法,想要进行转化,需要借助BC)
    • Bouncy Castle(“BC”,不推荐,实现比较复杂)

    下边只列出基于CC的工具类代码,至于基于JDK的代码可以参考“《Java加密与解密的艺术(第2版)》”,基于BC的代码可参考“慕课网”

    4.1.1、基于CC的SHA加密算法

    1 package com.util.sha;
     2 
     3 import java.io.UnsupportedEncodingException;
     4 import java.security.NoSuchAlgorithmException;
     5 import org.apache.commons.codec.digest.DigestUtils;
     6 /**
     7  * 基于Commons Codec的SHA算法
     8  */
     9 public class SHACC {
    10     private static final String ENCODING = "UTF-8";
    11     
    12     /**
    13      * SHA加密,加密后的结果为二进制字节数组
    14      */
    15     public static byte[] encode(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException {
    16         //return DigestUtils.sha1(data.getBytes(ENCODING));//SHA-1
    17         return DigestUtils.sha256(data.getBytes(ENCODING));//SHA-256
    18     }
    19     
    20     /**
    21      *SHA加密,加密后的结果为二进制字节数组,并且在这里将二进制字节数组转为了16进制字符串
    22      */
    23     public static String encodeSHAHex(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException {
    24         //return new String(DigestUtils.sha1Hex(data.getBytes(ENCODING)));
    25         return new String(DigestUtils.sha256Hex(data.getBytes(ENCODING)));
    26     }
    27     
    28     /**
    29      * 测试
    30      * @param args
    31      * @throws UnsupportedEncodingException 
    32      * @throws NoSuchAlgorithmException 
    33      */
    34     public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    35         
    36         String data = "找一个好姑娘做老婆是我的梦 想!";
    37         /*************测试encode()**************/
    38         System.out.println("原文-->"+data);
    39         byte[] encodedByte = SHACC.encode(data);
    40         System.out.println("加密后-->"+encodedByte);
    41         byte[] encodedByte2 = SHACC.encode(data);
    42         System.out.println("加密后-->"+encodedByte2);
    43         for(int i=0;i<encodedByte.length;i++){
    44             System.out.println(encodedByte[i]==encodedByte2[i]);
    45         }
    46         /*************测试encodeSHAHex()**************/
    47         System.out.println("原文-->"+data);
    48         String encodedStr = SHACC.encodeSHAHex(data);
    49         System.out.println("加密后-->"+encodedStr);
    50         String encodedStr2 = SHACC.encodeSHAHex(data);
    51         System.out.println("加密后-->"+encodedStr2);
    52         System.out.println(encodedStr.equals(encodedStr2));
    53     }
    54 }

    在我们需要采用相应的sha算法的时候,只需选用不同的函数即可(具体查询Commons Codec的API即可,链接在第五章末尾)。

    jar包的引入参考第二章的第一个例子进行即可,在测试的过程中,自己去试着看看“同一个消息多次进行SHA加密后结果是不是相同”;

    在encode()方法的测试中判断两个byte[]是否相等:按索引依次比较两个字节数组中的元素是否相同即可(如果使用main方法去测的话);如果使用Junit,直接使用assertArrayEquals(array1,array2)即可

    5.1、mac(又称为Hmac)

    原理:在md与sha系列算法的基础上加入了密钥,是三大常用的消息摘要算法中最安全的一个。

    常用的mac算法:

    • HmacMD5
    • HmacSHA1
    • HmacSHA256

    5.2、实现方式

    • JDK(缺少二进制字节数组转十六进制的工具,可借助CC或BC的工具类完成)
    • Commons Codec(CC,在1.10版本中加入的,其中,产生相应算法密钥的API没有找到,如果有人找到了,请和我讲一下,谢谢
    • Bouncy Castle(BC,比较麻烦,具体参考“慕课网”)

    5.2.1、基于JDK实现的Hmac系列算法

     1 package com.util.mac;
     2 
     3 import java.io.UnsupportedEncodingException;
     4 import java.security.InvalidKeyException;
     5 import java.security.NoSuchAlgorithmException;
     6 
     7 import javax.crypto.KeyGenerator;
     8 import javax.crypto.Mac;
     9 import javax.crypto.SecretKey;
    10 import javax.crypto.spec.SecretKeySpec;
    11 
    12 import org.bouncycastle.util.encoders.Hex;
    13 
    14 /**
    15  * 基于JDK的HmacMD5算法
    16  */
    17 public class HmacMD5JDK {
    18     private static final String ENCODING = "UTF-8";
    19     private static final String ALGORITHM = "HmacMD5";//指定具体算法HmacMD5,HmacSHA1,HmacSHA256
    20     
    21     /**
    22      * 产生密钥两种方式 1)是由jdk自己来产生的,2)我们可以自己指定一个字节数组
    23      * 注意:密钥是以二进制字节数组存储的
    24      */
    25     public static byte[] getKey() throws NoSuchAlgorithmException{
    26         SecretKey key = KeyGenerator.getInstance(ALGORITHM).generateKey();
    27         return key.getEncoded();
    28     }
    29     
    30     /**
    31      * HmacMD5加密
    32      * @param data     带加密数据
    33      * @param keyByte  密钥
    34      */
    35     public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException, 
    36                                                                     InvalidKeyException, 
    37                                                                     IllegalStateException, 
    38                                                                     UnsupportedEncodingException {
    39         SecretKey key = new SecretKeySpec(keyByte, ALGORITHM);//还原密钥
    40         Mac mac = Mac.getInstance(key.getAlgorithm());
    41         mac.init(key);//为mac实例初始化密钥
    42         return mac.doFinal(data.getBytes(ENCODING));
    43     }
    44     
    45     /**
    46      * HmacMD5加密,并转为16进制
    47      */
    48     public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException, 
    49                                                                               UnsupportedEncodingException, 
    50                                                                               InvalidKeyException, 
    51                                                                               IllegalStateException {
    52         byte[] encodedByte = encode(data, keyByte);
    53         return new String(Hex.encode(encodedByte));//借助BC
    54         //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
    55     }
    56     
    57     /**
    58      * 测试
    59      * @throws IllegalStateException 
    60      * @throws InvalidKeyException 
    61      */
    62     public static void main(String[] args) throws UnsupportedEncodingException, 
    63                                                   NoSuchAlgorithmException, 
    64                                                   InvalidKeyException, 
    65                                                   IllegalStateException {
    66         String data = "找一个好姑娘做老婆是我的梦 想!";
    67         /*************测试encode()**************/
    68         System.out.println("原文-->"+data);
    69         byte[] keyByte = HmacMD5JDK.getKey(); 
    70         byte[] encodedByte = HmacMD5JDK.encode(data, keyByte);
    71         System.out.println("加密后-->"+encodedByte);
    72         byte[] encodedByte2 = HmacMD5JDK.encode(data, keyByte);
    73         System.out.println("加密后-->"+encodedByte2);
    74         for(int i=0;i<encodedByte.length;i++){
    75             System.out.println(encodedByte[i]==encodedByte2[i]);
    76         }
    77         /*************测试encodeHmacMD5Hex()**************/
    78         System.out.println("原文-->"+data);
    79         String encodedStr = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);
    80         System.out.println("加密后-->"+encodedStr);
    81         String encodedStr2 = HmacMD5JDK.encodeHmacMD5Hex(data, keyByte);
    82         System.out.println("加密后-->"+encodedStr2);
    83         System.out.println(encodedStr.equals(encodedStr2));
    84     }
    85 }

    注意几点:

    • 产生密钥两种方式:1)直接使用JDK的类(如上边代码所示)2)自己指定字节数组(参考5.2.1)
    • 密钥是一个二进制数组,当然为了提高可读性,可以使用Base64加密后,在传递可对方
    • 在实际使用中,我们可以将密钥产生后,发送者通过安全途径(线下传递等)传给接收方。
    • 在上述的测试中,去测一下同一个消息在使用同一个密钥的情况下,多次mac后结果是否相同。
    • 想切换算法,只需要修改ALGORITHM常数即可,当然如果在实际项目中需要用到多种算法,并且需要实现平滑切换,可以采用策略模式,这个以后会再讲。

    5.2.1、基于CC实现的Hmac系列算法

     1 package com.util.mac;
     2 
     3 import java.io.UnsupportedEncodingException;
     4 import java.security.InvalidKeyException;
     5 import java.security.NoSuchAlgorithmException;
     6 
     7 import org.apache.commons.codec.DecoderException;
     8 import org.apache.commons.codec.binary.Hex;
     9 import org.apache.commons.codec.digest.HmacUtils;
    10 
    11 /**
    12  * 基于CC的HmacMD5算法
    13  */
    14 public class HmacMD5CC {
    15     private static final String ENCODING = "UTF-8";
    16     /**
    17      * 产生密钥
    18      */
    19     public static byte[] getKey() throws NoSuchAlgorithmException, DecoderException{
    20         return Hex.decodeHex(new char[]{'a','b','c','d'}); 
    21     }
    22     
    23     /**
    24      * HmacMD5加密
    25      * @param data     带加密数据
    26      * @param keyByte  密钥
    27      */
    28     public static byte[] encode(String data, byte[] keyByte) throws NoSuchAlgorithmException, 
    29                                                                     InvalidKeyException, 
    30                                                                     IllegalStateException, 
    31                                                                     UnsupportedEncodingException {
    32         return HmacUtils.hmacMd5(keyByte, data.getBytes(ENCODING));
    33     }
    34     
    35     /**
    36      * HmacMD5加密,并转为16进制
    37      */
    38     public static String encodeHmacMD5Hex(String data, byte[] keyByte) throws NoSuchAlgorithmException, 
    39                                                                               UnsupportedEncodingException, 
    40                                                                               InvalidKeyException, 
    41                                                                               IllegalStateException {
    42         return HmacUtils.hmacMd5Hex(keyByte, data.getBytes(ENCODING));
    43     }
    44     
    45     /**
    46      * 测试
    47      * @throws IllegalStateException 
    48      * @throws InvalidKeyException 
    49      * @throws DecoderException 
    50      */
    51     public static void main(String[] args) throws UnsupportedEncodingException, 
    52                                                   NoSuchAlgorithmException, 
    53                                                   InvalidKeyException, 
    54                                                   IllegalStateException, 
    55                                                   DecoderException {
    56         String data = "找一个好姑娘做老婆是我的梦 想!";
    57         /*************测试encode()**************/
    58         System.out.println("原文-->"+data);
    59         byte[] keyByte = HmacMD5CC.getKey(); 
    60         byte[] encodedByte = HmacMD5CC.encode(data, keyByte);
    61         System.out.println("加密后-->"+encodedByte);
    62         byte[] encodedByte2 = HmacMD5CC.encode(data, keyByte);
    63         System.out.println("加密后-->"+encodedByte2);
    64         for(int i=0;i<encodedByte.length;i++){
    65             System.out.println(encodedByte[i]==encodedByte2[i]);
    66         }
    67         /*************测试encodeHmacMD5Hex()**************/
    68         System.out.println("原文-->"+data);
    69         String encodedStr = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);
    70         System.out.println("加密后-->"+encodedStr);
    71         String encodedStr2 = HmacMD5CC.encodeHmacMD5Hex(data, keyByte);
    72         System.out.println("加密后-->"+encodedStr2);
    73         System.out.println(encodedStr.equals(encodedStr2));
    74     }
    75 }

    注意:

    • CC很好的封装了jdk的底层,但是CC是在1.10版本中才添加了hmac系列算法
    • 在使用中,若想切换其他算法,只需要调用不同的方法即可,具体的查看本文最下边的CC1.10的API文档链接地址
    • 其中,生成密钥在这里是自己指定了一个字节数组,具体的有CC来产生相应算法的密钥的API并没有看到,如果需要,可以自己去封装,当然,如果在CC中有相应的API,请大家和我讲一下,谢谢!

    14.1、数字签名算法

    特点:

    • 非对称加密算法+消息摘要算法的结合体
    • 抗否认性、认证数据来源、防止数据被篡改(具体意思与做法查看下边的过程与类比部分)
    • 私钥加密(签名)、公钥解密(验证)

    过程:

    1)消息发送者产生一个密钥对(私钥+公钥),然后将公钥发送给消息接收者

    2)消息发送者使用消息摘要算法对原文进行加密(加密后的密文称作摘要)

    3)消息发送者将上述的摘要使用私钥加密得到密文--这个过程就被称作签名处理,得到的密文就被称作签名(注意,这个签名是名词)

    4)消息发送者将原文与密文发给消息接收者

    5)消息接收者使用公钥对密文(即签名)进行解密,得到摘要值content1

    6)消息接收者使用与消息发送者相同的消息摘要算法对原文进行加密,得到摘要值content2

    7)比较content1是不是与content2相等,若相等,则说明消息没有被篡改(消息完整性),也说明消息却是来源于上述的消息发送方(因为其他人是无法伪造签名的,这就完成了“抗否认性”和“认证消息来源”)

    类比:

    手写签名:

    • 张三在合同上签了自己的名字,这样张三在后来想否认自己的这个合同内容时,就不行了(抗否认性)
    • 在张三签过名之后,若合同内容又发生了变化,这个时候签名就可以看做无效了
    • 当然,我们通过合同上张三的签名,我们就可以知道签名的来源是张三(认证数据来源)

    常见的数字签名算法:

    • RSA(数字签名算法的经典,也是最常用的数字签名算法)
    • DSA(是后续数字签名算法的基础)
    • ECDSA(ECC+DSA的结合体,相较于其他数字签名算法,速度快,强度高,签名短,但是使用还没有RSA广泛)

    14.2、RSA

    常见算法:

    • MD5WithRSA(JDK6)
    • SHA1WithRSA(JDK6)
    • SHA256WithRSA(>=JDK1.6.45,Bouncy Castle-->简称BC)

    注意:在《Java加密与解密(第二版)》一书中,说JDK6不支持SHA256WithRSA,但是经过我自己测试1.6.45是支持的。

    实现方式:(参考上边三行)

    • JDK
    • BC

    14.2.1、基于JDK6实现的MD5WithRSA或SHA1WithRSA或SHA256WithRSA算法

    1 package com.uti.rsa.digital;
      2 
      3 import java.io.UnsupportedEncodingException;
      4 import java.security.InvalidKeyException;
      5 import java.security.KeyFactory;
      6 import java.security.KeyPair;
      7 import java.security.KeyPairGenerator;
      8 import java.security.NoSuchAlgorithmException;
      9 import java.security.PrivateKey;
     10 import java.security.PublicKey;
     11 import java.security.Signature;
     12 import java.security.SignatureException;
     13 import java.security.spec.InvalidKeySpecException;
     14 import java.security.spec.PKCS8EncodedKeySpec;
     15 import java.security.spec.X509EncodedKeySpec;
     16 
     17 import org.apache.commons.codec.binary.Base64;
     18 
     19 /**
     20  * 基于BC的RSA数字签名算法
     21  */
     22 public class RSACoderBC {
     23     private static final String ENCODING = "UTF-8";
     24     private static final String KEY_ALGORITHM = "RSA";//非对称加密密钥算法
     25     private static final String SIGNATURE_ALGORITHM = "MD5withRSA";//指定数字签名算法(可以换成SHA1withRSA或SHA256withRSA)
     26     private static final int KEY_SIZE = 512;//非对称密钥长度(512~1024之间的64的整数倍)
     27     
     28     /**
     29      * 生成发送方密钥对
     30      */
     31     public static KeyPair initKey() throws NoSuchAlgorithmException{
     32         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);//密钥对生成器
     33         keyPairGenerator.initialize(KEY_SIZE);//指定密钥长度
     34         KeyPair keyPair = keyPairGenerator.generateKeyPair();//生成密钥对
     35         return keyPair;
     36     }
     37     
     38     /**
     39      * 还原公钥
     40      * @param pubKey 二进制公钥
     41      */
     42     public static PublicKey toPublicKey(byte[] pubKey) throws NoSuchAlgorithmException, 
     43                                                               InvalidKeySpecException{
     44         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);//密钥工厂
     45         return keyFactory.generatePublic(new X509EncodedKeySpec(pubKey));//还原公钥
     46     }
     47     
     48     /**
     49      * 还原私钥
     50      * @param priKey 二进制私钥
     51      */
     52     public static PrivateKey toPrivateKey(byte[] priKey) throws NoSuchAlgorithmException, 
     53                                                                 InvalidKeySpecException{
     54         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);//密钥工厂
     55         return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(priKey));//还原私钥
     56     }
     57     
     58     /**
     59      * 私钥加密(签名)
     60      * @param data     待加密数据
     61      * @param keyByte  私钥
     62      */
     63     public static byte[] encryptPriKey(String data, byte[] keyByte) throws NoSuchAlgorithmException, 
     64                                                                            InvalidKeySpecException, 
     65                                                                            InvalidKeyException, 
     66                                                                            SignatureException, 
     67                                                                            UnsupportedEncodingException {
     68         PrivateKey priKey = toPrivateKey(keyByte);//还原私钥
     69 
     70         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
     71         signature.initSign(priKey);
     72         signature.update(data.getBytes(ENCODING));
     73         
     74         return signature.sign();
     75     }
     76     
     77     /**
     78      * 公钥解密(验证)
     79      * @param data        原文(待加密数据,也成为“待校验数据”)
     80      * @param keyByte    公钥
     81      * @param sign        密文(也称作“签名”)
     82      */
     83     public static boolean decryptPubKey(String data, byte[] keyByte, byte[] sign) throws NoSuchAlgorithmException, 
     84                                                                                          InvalidKeySpecException, 
     85                                                                                          InvalidKeyException, 
     86                                                                                          SignatureException, 
     87                                                                                          UnsupportedEncodingException {
     88         PublicKey pubKey = toPublicKey(keyByte);//还原公钥
     89         
     90         Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
     91         signature.initVerify(pubKey);
     92         signature.update(data.getBytes(ENCODING));
     93         
     94         return signature.verify(sign);
     95     }
     96     
     97     /**
     98      * 获取公钥
     99      */
    100     public static byte[] getPublicKey(KeyPair keyPair){
    101         return keyPair.getPublic().getEncoded();
    102     }
    103     
    104     /**
    105      * 获取私钥
    106      */
    107     public static byte[] getPrivateKey(KeyPair keyPair){
    108         return keyPair.getPrivate().getEncoded();
    109     }
    110     
    111     /**
    112      * 测试
    113      */
    114     public static void main(String[] args) throws NoSuchAlgorithmException, 
    115                                                   InvalidKeyException, 
    116                                                   InvalidKeySpecException, 
    117                                                   SignatureException, 
    118                                                   UnsupportedEncodingException {
    119         byte[] pubKey1;//甲方公钥
    120         byte[] priKey1;//甲方私钥
    121         
    122         /*********************测试是否可以正确生成以上2个key*********************/
    123         KeyPair keyPair1 = RSACoderBC.initKey();//生成甲方密钥对
    124         pubKey1 = RSACoderBC.getPublicKey(keyPair1);
    125         priKey1 = RSACoderBC.getPrivateKey(keyPair1);
    126         
    127         System.out.println("甲方公钥pubKey1-->"+Base64.encodeBase64String(pubKey1)+"@@pubKey1.length-->"+pubKey1.length);
    128         System.out.println("甲方私钥priKey1-->"+Base64.encodeBase64String(priKey1)+"@@priKey1.length-->"+priKey1.length);
    129         
    130         /*********************测试甲方使用私钥加密数据向乙方发送,乙方使用公钥解密数据*********************/
    131         System.out.println("甲方-->乙方");
    132         String data = "找一个好姑娘啊!你好吗,孩子";
    133         byte[] encodeStr = RSACoderBC.encryptPriKey(data, priKey1);//加密(签名)
    134         System.out.println("甲方加密后的数据-->"+Base64.encodeBase64String(encodeStr)+"@@encodeStr.length-->"+encodeStr.length);
    135         boolean decodeStr = RSACoderBC.decryptPubKey(data, pubKey1, encodeStr);
    136         System.out.println("乙方检验结果-->"+decodeStr);
    137     }
    138 }

    注意点:

    • 代码与RSA非对称加密算法(查看第十二章)基本一样,只是将其中的私钥加密与公钥解密部分的加解密算法改为签名和验证算法,当然没有“公钥加密,私钥解密”
  • 相关阅读:
    HTTP、HTTP2
    1-1 用本地代码调试线上环境代码
    js判断触摸方向
    1-1 node 基础
    1-2 nodejs小节 文件读取
    c++ 递归斐波那契算法及时间复杂度
    十进制转换成二进制以 二进制转换成 8进制和16进制
    centos6.5 安装cmake 3.3.2
    回文字符串
    -Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable
  • 原文地址:https://www.cnblogs.com/hanease/p/16297945.html
Copyright © 2020-2023  润新知