DSA
DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!也就是说传输中的数据可以不再加密,接收方获得数据后,拿到公钥与签名比对数据是否有效!
通过java代码实现如下:Coder类见 java加密技术(一)
Java代码
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.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * DSA安全编码组件 * */ public abstract class DSACoder extends Coder { /** * 可以使用DSA方式获得签名,也可以使用RSA方式获得签名,注意成对儿出现。 * * <code> * public static final String KEY_ALGORITHM = "RSA"; * public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; * </code> **/ public static final String KEY_ALGORITHM = "DSA"; public static final String SIGNATURE_ALGORITHM = "DSA"; /** * 默认种子 */ private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3"; private static final String PUBLIC_KEY = "DSAPublicKey"; private static final String PRIVATE_KEY = "DSAPrivateKey"; /** * 用私钥对信息生成数字签名 * * @param data * 加密数据 * @param privateKey * 私钥 * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64编码的私钥 byte[] keyBytes = decryptBASE64(privateKey); // 构造PKCS8EncodedKeySpec对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私钥匙对象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私钥对信息生成数字签名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校验数字签名 * @param data * 加密数据 * @param publicKey * 公钥 * @param sign * 数字签名 * * @return 校验成功返回true 失败返回false * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { // 解密由base64编码的公钥 byte[] keyBytes = decryptBASE64(publicKey); // 构造X509EncodedKeySpec对象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取公钥匙对象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); // 验证签名是否正常 return signature.verify(decryptBASE64(sign)); } /** * 生成密钥 * * @param seed * 种子 * @return 密钥对象 * @throws Exception */ public static Map<String, Object> initKey(String seed) throws Exception { KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM); // 初始化随机产生器 SecureRandom secureRandom = new SecureRandom(); secureRandom.setSeed(seed.getBytes()); keygen.initialize(1024, secureRandom); KeyPair keys = keygen.genKeyPair(); PublicKey publicKey = keys.getPublic(); PrivateKey privateKey = keys.getPrivate(); Map<String, Object> map = new HashMap<String, Object>(2); map.put(PUBLIC_KEY, publicKey); map.put(PRIVATE_KEY, privateKey); return map; } /** * 默认生成密钥 * * @return 密钥对象 * @throws Exception */ public static Map<String, Object> initKey() throws Exception { return initKey(DEFAULT_SEED); } /** * 取得私钥 * * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公钥 * * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } } 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.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; /** * DSA安全编码组件 * */ public abstract class DSACoder extends Coder { /** * 可以使用DSA方式获得签名,也可以使用RSA方式获得签名,注意成对儿出现。 * * <code> * public static final String KEY_ALGORITHM = "RSA"; * public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; * </code> **/ public static final String KEY_ALGORITHM = "DSA"; public static final String SIGNATURE_ALGORITHM = "DSA"; /** * 默认种子 */ private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3"; private static final String PUBLIC_KEY = "DSAPublicKey"; private static final String PRIVATE_KEY = "DSAPrivateKey"; /** * 用私钥对信息生成数字签名 * * @param data * 加密数据 * @param privateKey * 私钥 * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { // 解密由base64编码的私钥 byte[] keyBytes = decryptBASE64(privateKey); // 构造PKCS8EncodedKeySpec对象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取私钥匙对象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec); // 用私钥对信息生成数字签名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return encryptBASE64(signature.sign()); } /** * 校验数字签名 * @param data * 加密数据 * @param publicKey * 公钥 * @param sign * 数字签名 * * @return 校验成功返回true 失败返回false * @throws Exception * */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { // 解密由base64编码的公钥 byte[] keyBytes = decryptBASE64(publicKey); // 构造X509EncodedKeySpec对象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); // 取公钥匙对象 PublicKey pubKey = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); // 验证签名是否正常 return signature.verify(decryptBASE64(sign)); } /** * 生成密钥 * * @param seed * 种子 * @return 密钥对象 * @throws Exception */ public static Map<String, Object> initKey(String seed) throws Exception { KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM); // 初始化随机产生器 SecureRandom secureRandom = new SecureRandom(); secureRandom.setSeed(seed.getBytes()); keygen.initialize(1024, secureRandom); KeyPair keys = keygen.genKeyPair(); PublicKey publicKey = keys.getPublic(); PrivateKey privateKey = keys.getPrivate(); Map<String, Object> map = new HashMap<String, Object>(2); map.put(PUBLIC_KEY, publicKey); map.put(PRIVATE_KEY, privateKey); return map; } /** * 默认生成密钥 * * @return 密钥对象 * @throws Exception */ public static Map<String, Object> initKey() throws Exception { return initKey(DEFAULT_SEED); } /** * 取得私钥 * * @param keyMap * @return * @throws Exception */ public static String getPrivateKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PRIVATE_KEY); return encryptBASE64(key.getEncoded()); } /** * 取得公钥 * * @param keyMap * @return * @throws Exception */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return encryptBASE64(key.getEncoded()); } } 不仅可以使用DSA算法,同样也可以使用RSA算法做数字签名,但要注意成对出现: public static final String KEY_ALGORITHM = "RSA"; public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; 再给出一个测试类: Java代码 import static org.junit.Assert.*; import java.util.Map; import org.junit.Test; /** * */ public class DSACoderTest { @Test public void test() throws Exception { String inputStr = "abc"; byte[] data = inputStr.getBytes(); // 构建密钥 Map<String, Object> keyMap = DSACoder.initKey(); // 获得密钥 String publicKey = DSACoder.getPublicKey(keyMap); String privateKey = DSACoder.getPrivateKey(keyMap); System.err.println("公钥:\r" + publicKey); System.err.println("私钥:\r" + privateKey); // 产生签名 String sign = DSACoder.sign(data, privateKey); System.err.println("签名:\r" + sign); // 验证签名 boolean status = DSACoder.verify(data, publicKey, sign); System.err.println("状态:\r" + status); assertTrue(status); } } import static org.junit.Assert.*; import java.util.Map; import org.junit.Test; /** * */ public class DSACoderTest { @Test public void test() throws Exception { String inputStr = "abc"; byte[] data = inputStr.getBytes(); // 构建密钥 Map<String, Object> keyMap = DSACoder.initKey(); // 获得密钥 String publicKey = DSACoder.getPublicKey(keyMap); String privateKey = DSACoder.getPrivateKey(keyMap); System.err.println("公钥:\r" + publicKey); System.err.println("私钥:\r" + privateKey); // 产生签名 String sign = DSACoder.sign(data, privateKey); System.err.println("签名:\r" + sign); // 验证签名 boolean status = DSACoder.verify(data, publicKey, sign); System.err.println("状态:\r" + status); assertTrue(status); } }
控制台输出:
Console代码
公钥:
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp
RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn
xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE
C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv
5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9
21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=
私钥:
MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2
USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4
O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB
gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR
kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q
签名:
MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=
状态:
true
公钥:
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp
RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn
xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE
C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv
5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9
21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=
私钥:
MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2
USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4
O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB
gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR
kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q
签名:
MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=
状态:
true