DSA算法是1991年美国国家标准技术协会公布的数字签名标准(DSS)的核心算法。本质上是ElGamal数字签名算法,仅能与SHA系列算法结合,没有相应的MD融合算法。
DSA算法和RSA算法的异同
DSA算法是DSS技术的核心算法,与RSA算法的异同如下:
- 二者都是数字签名算法中的重要组成,缺一不可;
- DSA算法仅仅包含数字签名算法,没有密钥信息;
- DSA算法产生的数字证书无法进行加密通信,HTTPS不会使用这个算法;
- RSA算法包含加解密的密钥信息,同时又数字签名算法的作用;
算法家族
包含:SHA1withDSA、SHA224withDSA、SHA256withDSA、SHA384withDSA、SHA512withDSA五种算法。
密钥长度都是512-1024位。
Java中的算法实现
JDK 6实现了DSA算法,仅仅实现了SHA1withDSA算法。
示例代码,代码和RSA数字签名算法的一样,只不过是算法名字变了下,可见Java的API设计还是很不错的。
public class SignatureTest {
//唯一不一样的是这里
public static final String SIGN_ALGORITHM = "SHA1withDSA";
private static final String KEY_ALGORITHM = "RSA";
private static final int KEY_SIZE = 1024;
public static void main(String[] args) throws Exception {
KeyPair keyPair = initKey();
String input = "Sign Me";
byte[] sign = sign(input.getBytes(), keyPair.getPrivate().getEncoded());
boolean verify = verify(input.getBytes(), sign, keyPair.getPublic().getEncoded());
String msg = String.format("原始数据: %s , Sign : %s , Verify : %s", input, toBase64(sign), verify);
System.out.println(msg);
// 从二进制位角度看,sign的长度和密钥长度一致
System.out.println("Sign Size : " + (sign.length * 8) + " Key Size : " + KEY_SIZE);
}
public static KeyPair initKey() throws Exception {
KeyPairGenerator keyPairGr = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGr.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGr.generateKeyPair();
return keyPair;
}
public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
// 将byte[]的key格式化回来
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 获取算法实例并初始化
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
byte[] sign = signature.sign();
return sign;
}
public static boolean verify(byte[] data, byte[] sign, byte[] publicKey) throws Exception {
// 获取算法实例并初始化
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
Signature signature = Signature.getInstance(SIGN_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证数据和签名是否一致,放否认,放篡改
boolean verify = signature.verify(sign);
return verify;
}
public static String toBase64(byte[] data) {
return new String(Base64.getEncoder().encode(data));
}
}