起源
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。
RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
有码有真相
因为在加密过程中大多数是二进制的操作,为了展示我们先创建两个方法利用Base64实现对二进制数据的转换
获取密钥
public String encodeBase64(byte[] binaryData) {
return Base64.encode(binaryData);
}
public byte[] decodeBase64(String encoded) throws Base64DecodingException {
return Base64.decode(encoded);
}
代码中经常用到的字符串,我们先提取出来
private final String RSA_ALGORITHM = "RSA";
private final String SIGNATURE_ALGORITHM = "MD5withRSA";
private final String RSA_PUBLIC_KEY = "RSAPublicKey";
private final String RSA_PRIVATE_KEY = "RSAPrivateKey";
RSA算法是由私钥、公钥对数据进行操作,所以我们首先得先创建出一对密钥
/**
* 获取RSA算法私钥、公钥
*/
public Map<String, Object> getKey() throws NoSuchAlgorithmException {
Map<String, Object> keyMap = new HashMap<String, Object>(2);
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);
keyPairGen.initialize(1024);//1024代表密钥二进制位数
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
keyMap.put(RSA_PUBLIC_KEY, publicKey);
keyMap.put(RSA_PRIVATE_KEY, privateKey);
return keyMap;
}
对外抛出两个方法用来从Map里面取值,当然也可以直接通过Key取值
/**
* 获取公钥
*/
public String getPublicKey(Map<String, Object> map) {
Key key = (Key) map.get(RSA_PUBLIC_KEY);
return encodeBase64(key.getEncoded());
}
/**
* 获取私钥
*/
public String getPrivateKey(Map<String, Object> map) {
Key key = (Key) map.get(RSA_PRIVATE_KEY);
return encodeBase64(key.getEncoded());
}
私钥加密
/**
* 使用私钥对数据进行加密
*/
public byte[] encryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
byte[] keyBytes = decodeBase64(privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
Key priKey = keyFactory.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, priKey);
return cipher.doFinal(binaryData);
}
公钥加密
/**
* 使用公钥对数据进行加密
*/
public byte[] encryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
byte[] keyBytes = decodeBase64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
Key pubKey = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return cipher.doFinal(binaryData);
}
私钥解密
/**
* 使用私钥对数据进行解密
*/
public byte[] decryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
byte[] keyBytes = decodeBase64(privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
Key priKey = keyFactory.generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, priKey);
return cipher.doFinal(binaryData);
}
公钥解密
/**
* 使用公钥对数据进行解密
*/
public byte[] decryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
byte[] keyBytes = decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
Key pubKey = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, pubKey);
return cipher.doFinal(binaryData);
}
除了对数据进行加密意外,RSA算法还可用来签名
私钥签名
/**
* 使用私钥对数据进行签名
*/
public String sign(byte[] binaryData, String privateKey) throws Exception {
byte[] keyBytes = decodeBase64(privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(binaryData);
return encodeBase64(signature.sign());
}
公钥验证签名
/**
* 使用公钥对数据签名进行验证
*/
public boolean verify(byte[] binaryData, String publicKey, String sign) throws Exception {
byte[] keyBytes = decodeBase64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(binaryData);
return signature.verify(decodeBase64(sign));
}
下面是运行代码截图