Java读取RSA公私钥 密钥结构 加解密示例 非对称加解密padding
- 2017-02-22 22:01:00
- admin
- 原创 3358
一、读取RSA公私钥
1、Java使用RSA公钥格式是X.509
2、Java使用RSA私钥格式是PKCS#8
3、测试重复生成公私钥,公钥长度没有变化,私钥长度会有细微变化;
代码示例:
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512);//RSA keys must be at least 512 bits long
KeyPair key = keyGen.generateKeyPair();
byte[] pubBytes = null;
byte[] priBytes = null;
PublicKey pubKey = key.getPublic();
pubBytes = pubKey.getEncoded();
X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubBytes);
PrivateKey priKey = key.getPrivate();
priBytes = priKey.getEncoded();
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(priBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
PublicKey pubkey2 = factory.generatePublic(pubX509);
PrivateKey prikey2 = factory.generatePrivate(priPKCS8);
System.out.println(pubKey.equals(pubkey2));
System.out.println(priKey.equals(prikey2));
输出:
true
true
二、RSA密钥结构
代码示例:
public static void showKey() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
RSAPublicKey pubKey = (RSAPublicKey)key.getPublic();
RSAPrivateKey priKey = (RSAPrivateKey)key.getPrivate();
System.out.println(pubKey.getModulus());
System.out.println(pubKey.getPublicExponent());
System.out.println(priKey.getModulus());
System.out.println(priKey.getPrivateExponent());
}
输出:
97931010009304675619765519288
65537
97931010009304675619765519288
60796513011559424939588017727
三、RSA加解密示例
示例代码:
public static byte[] rsaEnc(PublicKey key, byte[] data) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] rsaDec(PrivateKey key, byte[] data) {
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(data);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void rsaDemo() throws Exception {
int keyLen = 1024;
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(keyLen);
KeyPair key = keyGen.generateKeyPair();
PublicKey pubKey = key.getPublic();
PrivateKey priKey = key.getPrivate();
byte[] data = "feinen".getBytes();
byte[] dataByte = new byte[keyLen/8];
System.arraycopy(data, 0, dataByte, 0, data.length);
byte[] ciphertext = rsaEnc(pubKey, dataByte);
System.out.println(ciphertext.length * 8);
byte[] plaintext = rsaDec(priKey, ciphertext);
System.out.println(plaintext.length * 8);
System.out.println(Hex.encodeHex(data));
System.out.println(Hex.encodeHex(ciphertext));
System.out.println(Hex.encodeHex(plaintext));
}
输出:
1024
1024
6665696e656e
984a463e98ab4f24a4eb36352187978d4f
6665696e656e0000000000000000000000
四、非对称加解密padding
RSA_NO_PADDING:
无填充模式,加密数据长度必须等于RSA_size(rsa);
RSA_PKCS1_PADDING:
即PKCS#1 v1.5 padding,目前使用最广泛的填充模式,加密数据长度必须小于RSA_size(rsa)−11;
会填充随机数导致每次加密结果不一样;
RSA_PKCS1_OAEP_PADDING:
定义在PKCS#1 v2.0,新项目建议使用这种填充模式,加密数据长度必须小于RSA_size(rsa)−41 ;
会填充随机数导致每次加密结果不一样;