RSA为经典数字签名算法 数字签名标准(Digital Signature Standard, DSS), DSS本质是ElGamal数字签名算法,DSS使用的算法成为数字签名算法(Digital Signature Algorithm, DSA)。
DSA与RSA是数字证书不可或缺的两种算法。DSA算法仅包含数字签名算法,使用DSA算法的数字证书无法进行加密通信,而RSA算法既包含加密/解密算法,同时兼具数字签名算法。
Alice与Bob作为消息交互双方,签名/验签流程如下
Java及Bouncy Castle对RSA实现细节
算法密钥长度密钥默认长度签名长度备注SHA1withDSA512~1024位(64倍数)1024-JavaSHA224withDSA、SHA256withDSA 、SHA384withDSA、SHA512withDSA512~1024位(64倍数)1024-Bouncy Castle实现下面是Java的DSA算法实现
package com.calvin.android.demo2.secrity; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * Author:cl * Email:lhzheng@grandstream.cn * Date:20-10-21 */ public class DSACoder { /** * 数字签名密钥算法 */ public static final String KEY_ALGORITHM = "DSA"; /** * 数字签名 * 签名/验证算法 */ public static final String SIGNATURE_ALGORITHM = "SHA1withDSA"; //公钥 Map Key private static final String PUBLIC_KEY = "DSAPublicKey"; //私钥Map key private static final String PRIVATE_KEY = "DSAPrivateKey"; /** * DSA密钥长度,默认1024位,密钥长度必须是64的倍数,范围512~1024位之间 */ private static final int KEY_SIZE = 1024; /** * 签名 * @param data 待签名数据 * @param privateKey 私钥 * @return byte[] 数字签名 * @throws Exception 异常 */ public static byte[] sign(byte[] data, byte[] privateKey) throws Exception { //转换私钥材料 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey); //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //取私钥对象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); //实例化Signature Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //初始化Signature signature.initSign(priKey); //更新 signature.update(data); //签名 return signature.sign(); } /** * 校验 * @param data 待校验数据 * @param publicKey 公钥 * @param sign 数字签名 * @return boolean 校验成功返回true,校验失败返回false * @throws Exception */ public static boolean verity(byte[] data, byte[] publicKey, byte[] sign) throws Exception{ //转换公钥材料 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey); //实例化密钥工厂 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); //生成公钥 PublicKey pubKey = keyFactory.generatePublic(keySpec); //实例化Signature Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); //初始化Signature signature.initVerify(pubKey); //更新 signature.update(data); //校验证 return signature.verify(sign); } public static Map<String, Object> initKey() throws Exception { //实例化密钥对生成器 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); //初始化密钥对生成器 keyPairGen.initialize(KEY_SIZE, new SecureRandom()); //生成密钥对 KeyPair keyPair = keyPairGen.generateKeyPair(); //公钥 DSAPublicKey publicKey = (DSAPublicKey)keyPair.getPublic(); //私钥 DSAPrivateKey privateKey = (DSAPrivateKey)keyPair.getPrivate(); //封装密钥 Map<String, Object> keyMap = new HashMap<>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } public static byte[] getPublicKey(Map<String, Object> keyMap){ return ((Key)keyMap.get(PUBLIC_KEY)).getEncoded(); } public static byte[] getPrivateKey(Map<String, Object> keyMap){ return ((Key)keyMap.get(PRIVATE_KEY)).getEncoded(); } }