最近接到一个需求,对接滴滴进行数据传输,其中用到了签名,研究了一下,现在记录下来。
说到这里,首先得知道什么是RSA。RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
通常先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。
以上内容来在百度百科。
更重要的数据则选择2048来保证数据的安全。
下面是加密签名、解密的例子
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* @ClassName TestSignature
* @Author king
* @Date 2020/3/27 10:09
* @Version V1.0
**/
public class TestSignature {
public static void main(String[] args) throws Exception {
KeyPair keyPair = generateKeyPair();
String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
String data = "data will be signature";
String signatureData = signature(data, privateKey);
boolean verify = verify(signatureData, data, publicKey);
System.out.println(verify);
}
/**
* @return java.security.KeyPair
* @Description 生成秘钥对
* @Date 2020/3/27 10:12
**/
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
rsa.initialize(2048);
return rsa.generateKeyPair();
}
/**
* @return String
* @Author wangwei
* @Description 加签
* @Date 2020/3/27 10:18
**/
public static String signature(String data, String privateKey) throws Exception {
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(generatePrivateKey(privateKey));
signature.update(data.getBytes());
byte[] sign = signature.sign();
return Base64.getEncoder().encodeToString(sign);
}
/**
* @return java.security.PrivateKey
* @Description 根据String生成privateKey
* @Date 2020/3/27 10:30
* @Param [string]
**/
public static PrivateKey generatePrivateKey(String string) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decode = Base64.getDecoder().decode(string.getBytes());
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decode);
return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
}
/**
* @return java.security.PublicKey
* @Description 根据String生成PublicKey
* @Date 2020/3/27 10:42
* @Param [string]
**/
public static PublicKey generatePublicKey(String string) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decode = Base64.getDecoder().decode(string.getBytes());
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);
return keyFactory.generatePublic(x509EncodedKeySpec);
}
/**
* @return boolean
* @Description 校验数据是否正确
* @Date 2020/3/27 10:42
* @Param [signatureData, data, publicKey]
**/
public static boolean verify(String signatureData, String data, String publicKey) throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
PublicKey publicKey1 = generatePublicKey(publicKey);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(publicKey1);
signature.update(data.getBytes());
return signature.verify(Base64.getDecoder().decode(signatureData));
}
}