hi,欢迎访问本站!
当前位置: 首页学习笔记正文

如何用java RSA生成生成公钥私钥(非对称加密)

用户投稿 学习笔记 15阅读

        最近,在做接口开发,用户调用对外发布的接口,并参照接口参数规格,即可向服务器数据库插入记录。

实现了接口接本功能,即将接口收到的记录插入到数据库中,这中间涉及到认证和数据完整性(识别并丢弃被第三方截取和修改的数据)的问题,考虑使用RSA算法。RSA是一种算法。 RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。

        RSA 加密或签名后的结果是不可读的二进制,使用时经常会转为 BASE64 码再传输。

        RSA 加密时,对要加密数据的大小有限制,最大不大于密钥长度。例如在使用 1024 bit 的密钥时(genrsa -out rsa_private_key.pem 1024),最大可以加密 1024/8=128 Bytes 的数据。数据大于 128 Bytes 时,需要对数据进行分组加密(如果数据超限,加解密时会失败,openssl 函数会返回 false),分组加密后的加密串拼接成一个字符串后发送给客户端。如果 Padding 填充方式使用默认的 OPENSSL_PKCS1_PADDING(需要占用 11 个字节用于填充),那么明文长度最多只能就是 128-11=117 Bytes。

        接收方解密时也需要分组。将加密后的原始二进制数据(对于经过 BASE64 的数据,需要解码),每 128 Bytes 分为一组,然后再进行解密。解密后的原文字符串拼接起来,就得到原始报文。

        下面是我用Java实现的RSA算法,来实现对认证授权码的加密和对信息记录的数字签名,其中,为了便展示认证码密文和信息数字签名,我将每字节差分为两个16进制的字符,以下所有测试数据的长度是理论上的2倍。

        在程序中我指定的1024 bit 的密钥,如果数据不超过密钥1024位,密文和签名为1024/=256,转换为16进制字符未512,经过测试生成的公钥长度:444,私钥的长度1700~1800之间,加密后为512。

       下面是源程序,分享一下。

package RSA;import java.io.ByteArrayOutputStream;import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.Signature;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Date;import java.util.HashMap;import java.util.Map;import javax.crypto.Cipher;import org.apache.commons.collections.set.SynchronizedSet;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public class CreateSecretKey { public static final String KEY_ALGORITHM = "RSA"; private static final String PUBLIC_KEY = "RSAPublicKey"; private static final String PRIVATE_KEY = "RSAPrivateKey"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** * RSA最大加密明文大小 * */ private static final int MAX_ENCRYPT_BLOCK = 117; /**   * RSA最大解密密文大小 */ private static final int MAX_DECRYPT_BLOCK = 128; private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5','6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; //获得公钥字符串 public static String getPublicKeyStr(Map<String, Object> keyMap) throws Exception { //获得map中的公钥对象 转为key对象 Key key = (Key) keyMap.get(PUBLIC_KEY); //编码返回字符串 return bytesToHex(encryptBASE64(key.getEncoded()).getBytes()); } //获得私钥字符串 public static String getPrivateKeyStr(Map<String, Object> keyMap) throws Exception { //获得map中的私钥对象 转为key对象 Key key = (Key) keyMap.get(PRIVATE_KEY); //编码返回字符串 return bytesToHex(encryptBASE64(key.getEncoded()).getBytes()); } //获取公钥 public static PublicKey getPublicKey(String key) throws Exception { byte[] keyBytes; keyBytes = (new BASE64Decoder()).decodeBuffer(key); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } //获取私钥 public static PrivateKey getPrivateKey(String key) throws Exception { byte[] keyBytes; keyBytes = (new BASE64Decoder()).decodeBuffer(key); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } //解码返回byte public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } //编码返回字符串 public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } //***************************签名和验证*******************************   public static String sign(byte[] data, String privateKeyStr) throws Exception { PrivateKey priK = getPrivateKey(new String(hexToBytes(privateKeyStr))); Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM); sig.initSign(priK); sig.update(data); return bytesToHex(sig.sign()); } public static boolean verify(byte[] data, String sign, String publicKeyStr) throws Exception { PublicKey pubK = getPublicKey(new String(hexToBytes(publicKeyStr))); Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM); sig.initVerify(pubK); sig.update(data); return sig.verify(hexToBytes(sign)); } //************************加密解密**************************   public static String encrypt(byte[] plainText, String publicKeyStr) throws Exception { PublicKey publicKey = getPublicKey(new String(hexToBytes(publicKeyStr))); Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); int inputLen = plainText.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; int i = 0; byte[] cache; while(inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK){ cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK); } else{ cache = cipher.doFinal(plainText, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptText = out.toByteArray(); out.close(); return bytesToHex(encryptText); } public static String decrypt(String encryptTextHex, String privateKeyStr) throws Exception { byte[] encryptText = hexToBytes(encryptTextHex); PrivateKey privateKey = getPrivateKey(new String(hexToBytes(privateKeyStr))); Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); int inputLen = encryptText.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while(inputLen - offSet > 0){ if(inputLen - offSet > MAX_DECRYPT_BLOCK){ cache = cipher.doFinal(encryptText, offSet, MAX_DECRYPT_BLOCK); } else{ cache = cipher.doFinal(encryptText, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] plainText = out.toByteArray(); out.close(); return new String(plainText); } public static Map<String, Object> initKey() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** * 将byte[]转换为16进制字符串 */ public static String bytesToHex(byte[] bytes) { //一个byte为8位,可用两个十六进制位标识 char[] buf = new char[bytes.length * 2]; int a = 0; int index = 0; for(byte b : bytes) { // 使用除与取余进行转换 if(b < 0) { a = 256 + b; } else { a = b; } buf[index++] = HEX_CHAR[a / 16]; buf[index++] = HEX_CHAR[a % 16]; } return new String(buf); } /** * 将16进制字符串转换为byte[] * * @param str * @return */ public static byte[] hexToBytes(String str) { if(str == null || str.trim().equals("")) { return new byte[0]; } byte[] bytes = new byte[str.length() / 2]; for(int i = 0; i < str.length() / 2; i++) { String subStr = str.substring(i * 2, i * 2 + 2); bytes[i] = (byte) Integer.parseInt(subStr, 16); } return bytes; } public static void main(String[] args) throws Exception { Map<String, Object> keyMap; String cipherText; String input = "10001eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; try { keyMap = initKey(); String publicKey = getPublicKeyStr(keyMap); System.out.println("公钥------------------"); System.out.println(publicKey); System.out.println("length: " + publicKey.length()); String privateKey = getPrivateKeyStr(keyMap); System.out.println("私钥------------------"); System.out.println(privateKey); System.out.println("length: " + privateKey.length()); System.out.println("测试可行性-------------------"); System.out.println("明文=======" + input); System.out.println("length: " + input.length()); cipherText = encrypt(input.getBytes(), publicKey); //加密后的东西  System.out.println("密文=======" + cipherText); System.out.println("length: " + cipherText.length()); //开始解密  String plainText = decrypt(cipherText, privateKey); System.out.println("解密后明文===== " + new String(plainText)); System.out.println("验证签名-----------"); String str = "被签名的内容sssssssassssssssssssssssssssssssssssssssss"; System.out.println("\n原文:" + str); String signature = sign(str.getBytes(), privateKey); System.out.println(signature); System.out.println(signature.length()); boolean status = verify(str.getBytes(), signature, publicKey); System.out.println("验证情况:" + status); } catch (Exception e) { e.printStackTrace(); } }}

编译执行,如下:

 

标签:
声明:无特别说明,转载请标明本文来源!
发布评论
正文 取消