1、RSA 签名算法概念
将 RSA 公钥密码算法按照数字签名的方式运用
2、RSA 签名算法分类(JDK实现)
(1)MD (MD2withRSA、MD5withRSA)
(2)SHA (SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA)
3、RSASignature 算法的编
3.1 签名
3.2 验证
4、RSASignature算法的实现
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
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.HashMap;
import java.util.Map;
public class RSASignatureUtil {
public static final String KEY_ALGORITHM = "RSA";
public static final String RSA_PUBLIC_KEY = "RSA_PUBLIC_KEY";
public static final String RSA_PRIVATE_KEY = "RSA_PRIVATE_KEY";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/**
* 生成 公私钥 密钥对
*
* @return
*/
public static Map<String, Object> initKey() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance(KEY_ALGORITHM);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>();
keyMap.put(RSA_PUBLIC_KEY, publicKey);
keyMap.put(RSA_PRIVATE_KEY, privateKey);
return keyMap;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 获取公钥
*
* @param keyMap
* @return
*/
public static byte[] getPublicKey(Map<String, Object> keyMap) {
RSAPublicKey key = (RSAPublicKey) keyMap.get(RSA_PUBLIC_KEY);
return key.getEncoded();
}
/**
* 获取密钥
*
* @param keyMap
* @return
*/
public static byte[] getPrivateKey(Map<String, Object> keyMap) {
RSAPrivateKey key = (RSAPrivateKey) keyMap.get(RSA_PRIVATE_KEY);
return key.getEncoded();
}
/**
* 对 原始数据 用 私钥 进行签名
*
* @param data
* 要签名的数据
* @param privateKey
* 私钥
* @return
*/
public static byte[] sign(byte[] data, byte[] privateKey) {
try {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return signature.sign();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 根据 原始数据、公钥、签名值 进行验证
*
* @param data
* 原始数据
* @param publicKey
* 公钥
* @param sign
* 签名
* @return
*/
public static boolean verify(byte[] data, byte[] publicKey, byte[] sign) {
try {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
boolean isValid = signature.verify(sign);
return isValid;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
字节数组转16进制
public class BytesToHex {
public static String fromBytesToHex(byte[] resultBytes) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < resultBytes.length; i++) {
if (Integer.toHexString(0xFF & resultBytes[i]).length() == 1) {
builder.append("0").append(
Integer.toHexString(0xFF & resultBytes[i]));
} else {
builder.append(Integer.toHexString(0xFF & resultBytes[i]));
}
}
return builder.toString();
}
}
测试代码
import java.util.Map;
public class Test {
// 待加密的明文
public static final String DATA = "test";
public static void main(String[] args) throws Exception {
// Test RSASignature
// 初始化密钥对
Map<String, Object> keyMap = RSASignatureUtil.initKey();
byte[] rsaPublicKey = RSASignatureUtil.getPublicKey(keyMap);
byte[] rsaPrivateKey = RSASignatureUtil.getPrivateKey(keyMap);
System.out.println("RSASignature PublicKey : "
+ BytesToHex.fromBytesToHex(rsaPublicKey));
System.out.println("RSASignature PrivateKey : "
+ BytesToHex.fromBytesToHex(rsaPrivateKey));
// Sign
byte[] sign = RSASignatureUtil.sign(DATA.getBytes(), rsaPrivateKey);
System.out.println("RSA Sign : " + BytesToHex.fromBytesToHex(sign));
// Verify
boolean isValid = RSASignatureUtil.verify((DATA).getBytes(),
rsaPublicKey, sign);
System.out.println("RSA Verify : " + isValid);
}
}