zoukankan      html  css  js  c++  java
  • Java中使用OpenSSL生成的RSA公私钥

    RSA是什么:RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。目前该加密方式广泛用于网上银行、数字签名等场合。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

    OpenSSL是什么:众多的密码算法、公钥基础设施标准以及SSL协议,或许这些有趣的功能会让你产生实现所有这些算法和标准的想法。果真如此,在对你表示敬佩的同时,还是忍不住提醒你:这是一个令人望而生畏的过程。这个工作不再是简单的读懂几本密码学专著和协议文档那么简单,而是要理解所有这些算法、标准和协议文档的每一个细节,并用你可能很熟悉的C语言字符一个一个去实现这些定义和过程。我们不知道你将需要多少时间来完成这项有趣而可怕的工作,但肯定不是一年两年的问题。OpenSSL就是由Eric A. Young和Tim J. Hudson两位绝世大好人自1995年就开始编写的集合众多安全算法的算法集合。通过命令或者开发库,我们可以轻松实现标准的公开算法应用。

    下面将介绍如何生成和使用秘钥。

    一、使用OpenSSL来生成私钥和公钥

    先验证系统上是否已经安装OpenSSL工具,Linux系统默认安装,但Windows默认没安装,需自行下载安装。请参考:Windows安装openssl

    λ openssl.exe version -a                              
    OpenSSL 1.1.0e  16 Feb 2017                           
    built on: reproducible build, date unspecified        
    platform:                                             
    compiler: cl " "VC-WIN64A                             
    OPENSSLDIR: "C:Program FilesCommon FilesSSL"       
    ENGINESDIR: "C:Program FilesOpenSSLlibengines-1_1"

    先来生成私钥:

    λ openssl genrsa -out rsa_private_key.pem 1024   
    Generating RSA private key, 1024 bit long modulus
    ....................................++++++       
    ........++++++                                   
    e is 65537 (0x010001)                            

    这条命令让openssl随机生成了一份私钥,加密长度是1024位。加密长度是指理论上最大允许”被加密的信息“长度的限制,也就是明文的长度限制。随着这个参数的增大(比方说2048),允许的明文长度也会增加,但同时也会造成计算复杂度的极速增长。一般推荐的长度就是1024位(128字节)。

    我们来看一下私钥的内容:

    -----BEGIN RSA PRIVATE KEY-----
    MIICWwIBAAKBgQDKeYC1p4iE7koV4JOlr+doVwIyhcI3q+q/MkBtPPN/w4J/2h3U
    LqaKXb54Fs8ON9rDFEVLShtbxX6fYx3vBEArrd516KWYYcx5la1vr1KHFtJScN/p
    3u0vwSj7ElE8U7aZwtkXL7iqGGLOyM1wQNqyIMi7nayPeOP2RzSYy2uUQQIDAQAB
    AoGAXWteJXJdHOhNKnbp6MKWhJ/Qlbr9d25M61amP0CmIMb2SUM8DBBSKvlBzmrH
    sgm3V9bcefaBVQB0gdnbj9JoQGzTOVNqVTVFg46a99uNpVja3HWdvZWDs4YKN4cE
    DGhHxu5DeyV/K4r3Paz/0mSBAu3Sn0l6ROejXX2GnKZFAAECQQDqjUhLSiTVAJfn
    rukJxEEJcvT0ELBxEu0OqiUNZCI2tbwWAP+KcZTJdJq5LR0O/ruFoUM+TskM+27y
    SrDuFLQBAkEA3P1PoFcYL7rs3vVG6LJZTNDz/rrG3wjMelVFUm3X7AiTqeChmh3Y
    HRvhoeRdP/O1Dc6MkmvKtMhmAFX3ZqngQQJASP38sIl7Wtoba9tP5F0xzCn9NvL2
    pcm5AiZK75bo2tPFm6dl3wSnw+XIvLXgZCk73EMqNPq5sJOSnE5IL188AQJAL39q
    i+XsVuXwX4OMeBtNQktvBgMTF4EGogyN18ewLxUw18RmN3/OoYMKngc9W69/7LXG
    VPpCGVUxR0Uy5agBgQJAGUa3uV3UTGBSxbbtII+9NRmlFTh+EsamP/iPErCr+pmI
    os8GvX7q24bkYvVddXu4hwLaplXrwTjNaAs1w390IQ==
    -----END RSA PRIVATE KEY-----

    内容都是标准的ASCII字符,开头一行和结尾一行有明显的标记,真正的私钥数据是中间的不规则字符。

    密钥文件最终将数据通过Base64编码进行存储。可以看到上述密钥文件内容每一行的长度都很规律。这是由于RFC2045中规定:The encoded output stream must be represented in lines of no more than 76 characters each。也就是说Base64编码的数据每行最多不超过76字符,对于超长数据需要按行分割。

    接下来根据私钥生成公钥:

    λ openssl rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout
    writing RSA key

    再来看一下公钥的内容:

    -----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKeYC1p4iE7koV4JOlr+doVwIy
    hcI3q+q/MkBtPPN/w4J/2h3ULqaKXb54Fs8ON9rDFEVLShtbxX6fYx3vBEArrd51
    6KWYYcx5la1vr1KHFtJScN/p3u0vwSj7ElE8U7aZwtkXL7iqGGLOyM1wQNqyIMi7
    nayPeOP2RzSYy2uUQQIDAQAB
    -----END PUBLIC KEY-----

    这时候的私钥还不能直接被使用,需要进行PKCS#8编码:

    λ openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt

    命令中指明了输入私钥文件为rsa_private_key.pem,输出私钥文件为pkcs8_rsa_private_key.pem,不采用任何二次加密(-nocrypt)

     如果不进行PKCS#8编码,Java在使用时会报错:

    java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    再来看一下,编码后的私钥文件是不是和之前的私钥文件不同了:

    -----BEGIN PRIVATE KEY-----
    MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMp5gLWniITuShXg
    k6Wv52hXAjKFwjer6r8yQG0883/Dgn/aHdQupopdvngWzw432sMURUtKG1vFfp9j
    He8EQCut3nXopZhhzHmVrW+vUocW0lJw3+ne7S/BKPsSUTxTtpnC2RcvuKoYYs7I
    zXBA2rIgyLudrI944/ZHNJjLa5RBAgMBAAECgYBda14lcl0c6E0qdunowpaEn9CV
    uv13bkzrVqY/QKYgxvZJQzwMEFIq+UHOaseyCbdX1tx59oFVAHSB2duP0mhAbNM5
    U2pVNUWDjpr3242lWNrcdZ29lYOzhgo3hwQMaEfG7kN7JX8rivc9rP/SZIEC7dKf
    SXpE56NdfYacpkUAAQJBAOqNSEtKJNUAl+eu6QnEQQly9PQQsHES7Q6qJQ1kIja1
    vBYA/4pxlMl0mrktHQ7+u4WhQz5OyQz7bvJKsO4UtAECQQDc/U+gVxgvuuze9Ubo
    sllM0PP+usbfCMx6VUVSbdfsCJOp4KGaHdgdG+Gh5F0/87UNzoySa8q0yGYAVfdm
    qeBBAkBI/fywiXta2htr20/kXTHMKf028valybkCJkrvluja08Wbp2XfBKfD5ci8
    teBkKTvcQyo0+rmwk5KcTkgvXzwBAkAvf2qL5exW5fBfg4x4G01CS28GAxMXgQai
    DI3Xx7AvFTDXxGY3f86hgwqeBz1br3/stcZU+kIZVTFHRTLlqAGBAkAZRre5XdRM
    YFLFtu0gj701GaUVOH4SxqY/+I8SsKv6mYiizwa9furbhuRi9V11e7iHAtqmVevB
    OM1oCzXDf3Qh
    -----END PRIVATE KEY-----

    至此,可用的密钥对已经生成好了,私钥使用pkcs8_rsa_private_key.pem,公钥采用rsa_public_key.pem。

    最近又遇到RSA加密的需求了,而且对方要求只能使用第一步生成的未经过PKCS#8编码的私钥文件。后来查看相关文献得知第一步生成的私钥文件编码是PKCS#1格式,这种格式Java其实是支持的,只不过多写两行代码而已:

    RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(priKeyData));  
    RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());  
    KeyFactory keyFactory= KeyFactory.getInstance("RSA");  
    PrivateKey priKey= keyFactory.generatePrivate(rsaPrivKeySpec); 

    首先将PKCS#1的私钥文件读取出来(注意去掉减号开头的注释内容),然后使用Base64解码读出的字符串,便得到priKeyData,也就是第一行代码中的参数。最后一行得到了私钥。接下来的用法就没什么区别了。

    二、编写Java代码实际测试

    RSA加密解密类:

      1 import java.io.BufferedReader;
      2 import java.io.BufferedWriter;
      3 import java.io.FileReader;
      4 import java.io.FileWriter;
      5 import java.io.IOException;
      6 import java.security.InvalidKeyException;
      7 import java.security.KeyFactory;
      8 import java.security.KeyPair;
      9 import java.security.KeyPairGenerator;
     10 import java.security.NoSuchAlgorithmException;
     11 import java.security.SecureRandom;
     12 
     13 import java.security.interfaces.RSAPrivateKey;
     14 import java.security.interfaces.RSAPublicKey;
     15 import java.security.spec.InvalidKeySpecException;
     16 import java.security.spec.PKCS8EncodedKeySpec;
     17 import java.security.spec.X509EncodedKeySpec;
     18 
     19 import javax.crypto.BadPaddingException;
     20 import javax.crypto.Cipher;
     21 import javax.crypto.IllegalBlockSizeException;
     22 import javax.crypto.NoSuchPaddingException;
     23 
     24 import org.apache.commons.codec.binary.Base64;
     25 
     26 public class RSAEncrypt {
     27     /**
     28      * 字节数据转字符串专用集合
     29      */
     30     private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
     31             '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
     32 
     33     /**
     34      * 随机生成密钥对
     35      */
     36     public static void genKeyPair(String filePath) {
     37         // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
     38         KeyPairGenerator keyPairGen = null;
     39         try {
     40             keyPairGen = KeyPairGenerator.getInstance("RSA");
     41         } catch (NoSuchAlgorithmException e) {
     42             e.printStackTrace();
     43         }
     44         // 初始化密钥对生成器,密钥大小为96-1024位
     45         keyPairGen.initialize(1024,new SecureRandom());
     46         // 生成一个密钥对,保存在keyPair中
     47         KeyPair keyPair = keyPairGen.generateKeyPair();
     48         // 得到私钥
     49         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
     50         // 得到公钥
     51         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
     52         try {
     53             // 得到公钥字符串
     54             Base64 base64 = new Base64();
     55             String publicKeyString = new String(base64.encode(publicKey.getEncoded()));
     56             // 得到私钥字符串
     57             String privateKeyString = new String(base64.encode(privateKey.getEncoded()));
     58             // 将密钥对写入到文件
     59             FileWriter pubfw = new FileWriter(filePath + "/publicKey.keystore");
     60             FileWriter prifw = new FileWriter(filePath + "/privateKey.keystore");
     61             BufferedWriter pubbw = new BufferedWriter(pubfw);
     62             BufferedWriter pribw = new BufferedWriter(prifw);
     63             pubbw.write(publicKeyString);
     64             pribw.write(privateKeyString);
     65             pubbw.flush();
     66             pubbw.close();
     67             pubfw.close();
     68             pribw.flush();
     69             pribw.close();
     70             prifw.close();
     71         } catch (Exception e) {
     72             e.printStackTrace();
     73         }
     74     }
     75 
     76     /**
     77      * 从文件中输入流中加载公钥
     78      * 
     79      * @param in
     80      *            公钥输入流
     81      * @throws Exception
     82      *             加载公钥时产生的异常
     83      */
     84     public static String loadPublicKeyByFile(String path) throws Exception {
     85         try {
     86             BufferedReader br = new BufferedReader(new FileReader(path
     87                     + "/publicKey.keystore"));
     88             String readLine = null;
     89             StringBuilder sb = new StringBuilder();
     90             while ((readLine = br.readLine()) != null) {
     91                 sb.append(readLine);
     92             }
     93             br.close();
     94             return sb.toString();
     95         } catch (IOException e) {
     96             throw new Exception("公钥数据流读取错误");
     97         } catch (NullPointerException e) {
     98             throw new Exception("公钥输入流为空");
     99         }
    100     }
    101 
    102     /**
    103      * 从字符串中加载公钥
    104      * 
    105      * @param publicKeyStr
    106      *            公钥数据字符串
    107      * @throws Exception
    108      *             加载公钥时产生的异常
    109      */
    110     public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
    111             throws Exception {
    112         try {
    113             Base64 base64 = new Base64();
    114             byte[] buffer = base64.decode(publicKeyStr);
    115             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    116             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
    117             return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    118         } catch (NoSuchAlgorithmException e) {
    119             throw new Exception("无此算法");
    120         } catch (InvalidKeySpecException e) {
    121             throw new Exception("公钥非法");
    122         } catch (NullPointerException e) {
    123             throw new Exception("公钥数据为空");
    124         }
    125     }
    126 
    127     /**
    128      * 从文件中加载私钥
    129      * 
    130      * @param keyFileName
    131      *            私钥文件名
    132      * @return 是否成功
    133      * @throws Exception
    134      */
    135     public static String loadPrivateKeyByFile(String path) throws Exception {
    136         try {
    137             BufferedReader br = new BufferedReader(new FileReader(path
    138                     + "/privateKey.keystore"));
    139             String readLine = null;
    140             StringBuilder sb = new StringBuilder();
    141             while ((readLine = br.readLine()) != null) {
    142                 sb.append(readLine);
    143             }
    144             br.close();
    145             return sb.toString();
    146         } catch (IOException e) {
    147             throw new Exception("私钥数据读取错误");
    148         } catch (NullPointerException e) {
    149             throw new Exception("私钥输入流为空");
    150         }
    151     }
    152 
    153     public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
    154             throws Exception {
    155         try {
    156             Base64 base64 = new Base64();
    157             byte[] buffer = base64.decode(privateKeyStr);
    158             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
    159             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    160             return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    161         } catch (NoSuchAlgorithmException e) {
    162             throw new Exception("无此算法");
    163         } catch (InvalidKeySpecException e) {
    164             throw new Exception("私钥非法");
    165         } catch (NullPointerException e) {
    166             throw new Exception("私钥数据为空");
    167         }
    168     }
    169 
    170     /**
    171      * 公钥加密过程
    172      * 
    173      * @param publicKey
    174      *            公钥
    175      * @param plainTextData
    176      *            明文数据
    177      * @return
    178      * @throws Exception
    179      *             加密过程中的异常信息
    180      */
    181     public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
    182             throws Exception {
    183         if (publicKey == null) {
    184             throw new Exception("加密公钥为空, 请设置");
    185         }
    186         Cipher cipher = null;
    187         try {
    188             // 使用默认RSA
    189             cipher = Cipher.getInstance("RSA");
    190             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    191             cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    192             byte[] output = cipher.doFinal(plainTextData);
    193             return output;
    194         } catch (NoSuchAlgorithmException e) {
    195             throw new Exception("无此加密算法");
    196         } catch (NoSuchPaddingException e) {
    197             e.printStackTrace();
    198             return null;
    199         } catch (InvalidKeyException e) {
    200             throw new Exception("加密公钥非法,请检查");
    201         } catch (IllegalBlockSizeException e) {
    202             throw new Exception("明文长度非法");
    203         } catch (BadPaddingException e) {
    204             throw new Exception("明文数据已损坏");
    205         }
    206     }
    207 
    208     /**
    209      * 私钥加密过程
    210      * 
    211      * @param privateKey
    212      *            私钥
    213      * @param plainTextData
    214      *            明文数据
    215      * @return
    216      * @throws Exception
    217      *             加密过程中的异常信息
    218      */
    219     public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
    220             throws Exception {
    221         if (privateKey == null) {
    222             throw new Exception("加密私钥为空, 请设置");
    223         }
    224         Cipher cipher = null;
    225         try {
    226             // 使用默认RSA
    227             cipher = Cipher.getInstance("RSA");
    228             cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    229             byte[] output = cipher.doFinal(plainTextData);
    230             return output;
    231         } catch (NoSuchAlgorithmException e) {
    232             throw new Exception("无此加密算法");
    233         } catch (NoSuchPaddingException e) {
    234             e.printStackTrace();
    235             return null;
    236         } catch (InvalidKeyException e) {
    237             throw new Exception("加密私钥非法,请检查");
    238         } catch (IllegalBlockSizeException e) {
    239             throw new Exception("明文长度非法");
    240         } catch (BadPaddingException e) {
    241             throw new Exception("明文数据已损坏");
    242         }
    243     }
    244 
    245     /**
    246      * 私钥解密过程
    247      * 
    248      * @param privateKey
    249      *            私钥
    250      * @param cipherData
    251      *            密文数据
    252      * @return 明文
    253      * @throws Exception
    254      *             解密过程中的异常信息
    255      */
    256     public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
    257             throws Exception {
    258         if (privateKey == null) {
    259             throw new Exception("解密私钥为空, 请设置");
    260         }
    261         Cipher cipher = null;
    262         try {
    263             // 使用默认RSA
    264             cipher = Cipher.getInstance("RSA");
    265             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    266             cipher.init(Cipher.DECRYPT_MODE, privateKey);
    267             byte[] output = cipher.doFinal(cipherData);
    268             return output;
    269         } catch (NoSuchAlgorithmException e) {
    270             throw new Exception("无此解密算法");
    271         } catch (NoSuchPaddingException e) {
    272             e.printStackTrace();
    273             return null;
    274         } catch (InvalidKeyException e) {
    275             throw new Exception("解密私钥非法,请检查");
    276         } catch (IllegalBlockSizeException e) {
    277             throw new Exception("密文长度非法");
    278         } catch (BadPaddingException e) {
    279             throw new Exception("密文数据已损坏");
    280         }
    281     }
    282 
    283     /**
    284      * 公钥解密过程
    285      * 
    286      * @param publicKey
    287      *            公钥
    288      * @param cipherData
    289      *            密文数据
    290      * @return 明文
    291      * @throws Exception
    292      *             解密过程中的异常信息
    293      */
    294     public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
    295             throws Exception {
    296         if (publicKey == null) {
    297             throw new Exception("解密公钥为空, 请设置");
    298         }
    299         Cipher cipher = null;
    300         try {
    301             // 使用默认RSA
    302             cipher = Cipher.getInstance("RSA");
    303             // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
    304             cipher.init(Cipher.DECRYPT_MODE, publicKey);
    305             byte[] output = cipher.doFinal(cipherData);
    306             return output;
    307         } catch (NoSuchAlgorithmException e) {
    308             throw new Exception("无此解密算法");
    309         } catch (NoSuchPaddingException e) {
    310             e.printStackTrace();
    311             return null;
    312         } catch (InvalidKeyException e) {
    313             throw new Exception("解密公钥非法,请检查");
    314         } catch (IllegalBlockSizeException e) {
    315             throw new Exception("密文长度非法");
    316         } catch (BadPaddingException e) {
    317             throw new Exception("密文数据已损坏");
    318         }
    319     }
    320 
    321     /**
    322      * 字节数据转十六进制字符串
    323      * 
    324      * @param data
    325      *            输入数据
    326      * @return 十六进制内容
    327      */
    328     public static String byteArrayToString(byte[] data) {
    329         StringBuilder stringBuilder = new StringBuilder();
    330         for (int i = 0; i < data.length; i++) {
    331             // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
    332             stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
    333             // 取出字节的低四位 作为索引得到相应的十六进制标识符
    334             stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
    335             if (i < data.length - 1) {
    336                 stringBuilder.append(' ');
    337             }
    338         }
    339         return stringBuilder.toString();
    340     }
    341 }

    签名及校验类:

      1 import java.security.KeyFactory;
      2 import java.security.PrivateKey;
      3 import java.security.PublicKey;
      4 import java.security.spec.PKCS8EncodedKeySpec;
      5 import java.security.spec.X509EncodedKeySpec;
      6 
      7 import org.apache.commons.codec.binary.Base64;
      8 
      9 /**
     10  * RSA签名验签类
     11  */
     12 public class RSASignature {
     13 
     14     /**
     15      * 签名算法
     16      */
     17     public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
     18 
     19     /**
     20      * RSA签名
     21      * 
     22      * @param content
     23      *            待签名数据
     24      * @param privateKey
     25      *            商户私钥
     26      * @param encode
     27      *            字符集编码
     28      * @return 签名值
     29      */
     30     public static String sign(String content, String privateKey, String encode) {
     31         try {
     32             Base64 base64 = new Base64();
     33             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(base64.decode(privateKey));
     34 
     35             KeyFactory keyf = KeyFactory.getInstance("RSA");
     36             PrivateKey priKey = keyf.generatePrivate(priPKCS8);
     37 
     38             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
     39 
     40             signature.initSign(priKey);
     41             signature.update(content.getBytes(encode));
     42 
     43             byte[] signed = signature.sign();
     44 
     45             return new String(base64.encode(signed));
     46         } catch (Exception e) {
     47             e.printStackTrace();
     48         }
     49 
     50         return null;
     51     }
     52 
     53     public static String sign(String content, String privateKey) {
     54         try {
     55             Base64 base64 = new Base64();
     56             PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(base64.decode(privateKey));
     57             KeyFactory keyf = KeyFactory.getInstance("RSA");
     58             PrivateKey priKey = keyf.generatePrivate(priPKCS8);
     59             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
     60             signature.initSign(priKey);
     61             signature.update(content.getBytes());
     62             byte[] signed = signature.sign();
     63             return new String(base64.encode(signed));
     64         } catch (Exception e) {
     65             e.printStackTrace();
     66         }
     67         return null;
     68     }
     69 
     70     /**
     71      * RSA验签名检查
     72      * 
     73      * @param content
     74      *            待签名数据
     75      * @param sign
     76      *            签名值
     77      * @param publicKey
     78      *            分配给开发商公钥
     79      * @param encode
     80      *            字符集编码
     81      * @return 布尔值
     82      */
     83     public static boolean doCheck(String content, String sign, String publicKey, String encode) {
     84         try {
     85             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
     86             Base64 base64 = new Base64();
     87             byte[] encodedKey = base64.decode(publicKey);
     88             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
     89 
     90             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
     91 
     92             signature.initVerify(pubKey);
     93             signature.update(content.getBytes(encode));
     94 
     95             boolean bverify = signature.verify(base64.decode(sign));
     96             return bverify;
     97 
     98         } catch (Exception e) {
     99             e.printStackTrace();
    100         }
    101 
    102         return false;
    103     }
    104 
    105     public static boolean doCheck(String content, String sign, String publicKey) {
    106         try {
    107             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    108             Base64 base64 = new Base64();
    109             byte[] encodedKey = base64.decode(publicKey);
    110             PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    111 
    112             java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
    113 
    114             signature.initVerify(pubKey);
    115             signature.update(content.getBytes());
    116 
    117             boolean bverify = signature.verify(base64.decode(sign));
    118             return bverify;
    119 
    120         } catch (Exception e) {
    121             e.printStackTrace();
    122         }
    123 
    124         return false;
    125     }
    126 
    127 }

    最后是一个MainTest:

     1 import org.apache.commons.codec.binary.Base64;
     2 
     3 public class MainTest {
     4 
     5     public static void main(String[] args) throws Exception {
     6         String filepath = "G:/tmp/";
     7 
     8         // RSAEncrypt.genKeyPair(filepath);
     9 
    10         Base64 base64 = new Base64();
    11 
    12         System.out.println("--------------公钥加密私钥解密过程-------------------");
    13         String plainText = "ihep_公钥加密私钥解密";
    14         // 公钥加密过程
    15         byte[] cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)),
    16                 plainText.getBytes());
    17         String cipher = new String(base64.encode(cipherData));
    18         // 私钥解密过程
    19         byte[] res = RSAEncrypt.decrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)),
    20                 base64.decode(cipher));
    21         String restr = new String(res);
    22         System.out.println("原文:" + plainText);
    23         System.out.println("加密:" + cipher);
    24         System.out.println("解密:" + restr);
    25         System.out.println();
    26 
    27         System.out.println("--------------私钥加密公钥解密过程-------------------");
    28         plainText = "ihep_私钥加密公钥解密";
    29         // 私钥加密过程
    30         cipherData = RSAEncrypt.encrypt(RSAEncrypt.loadPrivateKeyByStr(RSAEncrypt.loadPrivateKeyByFile(filepath)),
    31                 plainText.getBytes());
    32         cipher = new String(base64.encode(cipherData));
    33         // 公钥解密过程
    34         res = RSAEncrypt.decrypt(RSAEncrypt.loadPublicKeyByStr(RSAEncrypt.loadPublicKeyByFile(filepath)),
    35                 base64.decode(cipher));
    36         restr = new String(res);
    37         System.out.println("原文:" + plainText);
    38         System.out.println("加密:" + cipher);
    39         System.out.println("解密:" + restr);
    40         System.out.println();
    41 
    42         System.out.println("---------------私钥签名过程------------------");
    43         String content = "ihep_这是用于签名的原始数据";
    44         String signstr = RSASignature.sign(content, RSAEncrypt.loadPrivateKeyByFile(filepath));
    45         System.out.println("签名原串:" + content);
    46         System.out.println("签名串:" + signstr);
    47         System.out.println();
    48 
    49         System.out.println("---------------公钥校验签名------------------");
    50         System.out.println("签名原串:" + content);
    51         System.out.println("签名串:" + signstr);
    52 
    53         System.out.println("验签结果:" + RSASignature.doCheck(content, signstr, RSAEncrypt.loadPublicKeyByFile(filepath)));
    54         System.out.println();
    55 
    56     }
    57 }

    参考:

    http://blog.csdn.net/chaijunkun/article/details/7275632

    http://blog.csdn.net/wangqiuyun/article/details/42143957

  • 相关阅读:
    C#网络编程之Http请求
    使用 pdf.js 在网页中加载 pdf 文件
    程序员转型技术管理,这几本书不能错过
    HTTPS小结 、TSL、SSL
    clipboard 在 vue 项目中,on 事件监听回调多次执行
    Vue 引入 .md 文件,解析markdown语法
    Vue cli4.0 代理配置
    npm publish 一直报错 404
    JSON 多层对象获取键值
    Tomcat8配置Https协议,Tomcat配置Https安全访问,Tomcat Https配置
  • 原文地址:https://www.cnblogs.com/warehouse/p/6890772.html
Copyright © 2011-2022 走看看