zoukankan      html  css  js  c++  java
  • 介绍DSA数字签名,非对称加密的另一种实现

    接下来我们介绍DSA数字签名,非对称加密的另一种实现。
    DSA
    DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输过程中不被修改。数字签名,是单向加密的升级!


    通过java代码实现如下:Coder类见 Java加密技术(一)

    Java代码  收藏代码
    1. import java.security.Key;  
    2. import java.security.KeyFactory;  
    3. import java.security.KeyPair;  
    4. import java.security.KeyPairGenerator;  
    5. import java.security.PrivateKey;  
    6. import java.security.PublicKey;  
    7. import java.security.SecureRandom;  
    8. import java.security.Signature;  
    9. import java.security.interfaces.DSAPrivateKey;  
    10. import java.security.interfaces.DSAPublicKey;  
    11. import java.security.spec.PKCS8EncodedKeySpec;  
    12. import java.security.spec.X509EncodedKeySpec;  
    13. import java.util.HashMap;  
    14. import java.util.Map;  
    15.   
    16. /** 
    17.  * DSA安全编码组件 
    18.  *  
    19.  * @author 梁栋 
    20.  * @version 1.0 
    21.  * @since 1.0 
    22.  */  
    23. public abstract class DSACoder extends Coder {  
    24.   
    25.     public static final String ALGORITHM = "DSA";  
    26.   
    27.     /** 
    28.      * 默认密钥字节数 
    29.      *  
    30.      * <pre> 
    31.      * DSA  
    32.      * Default Keysize 1024   
    33.      * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive). 
    34.      * </pre> 
    35.      */  
    36.     private static final int KEY_SIZE = 1024;  
    37.   
    38.     /** 
    39.      * 默认种子 
    40.      */  
    41.     private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";  
    42.   
    43.     private static final String PUBLIC_KEY = "DSAPublicKey";  
    44.     private static final String PRIVATE_KEY = "DSAPrivateKey";  
    45.   
    46.     /** 
    47.      * 用私钥对信息生成数字签名 
    48.      *  
    49.      * @param data 
    50.      *            加密数据 
    51.      * @param privateKey 
    52.      *            私钥 
    53.      *  
    54.      * @return 
    55.      * @throws Exception 
    56.      */  
    57.     public static String sign(byte[] data, String privateKey) throws Exception {  
    58.         // 解密由base64编码的私钥  
    59.         byte[] keyBytes = decryptBASE64(privateKey);  
    60.   
    61.         // 构造PKCS8EncodedKeySpec对象  
    62.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);  
    63.   
    64.         // KEY_ALGORITHM 指定的加密算法  
    65.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    66.   
    67.         // 取私钥匙对象  
    68.         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);  
    69.   
    70.         // 用私钥对信息生成数字签名  
    71.         Signature signature = Signature.getInstance(keyFactory.getAlgorithm());  
    72.         signature.initSign(priKey);  
    73.         signature.update(data);  
    74.   
    75.         return encryptBASE64(signature.sign());  
    76.     }  
    77.   
    78.     /** 
    79.      * 校验数字签名 
    80.      *  
    81.      * @param data 
    82.      *            加密数据 
    83.      * @param publicKey 
    84.      *            公钥 
    85.      * @param sign 
    86.      *            数字签名 
    87.      *  
    88.      * @return 校验成功返回true 失败返回false 
    89.      * @throws Exception 
    90.      *  
    91.      */  
    92.     public static boolean verify(byte[] data, String publicKey, String sign)  
    93.             throws Exception {  
    94.   
    95.         // 解密由base64编码的公钥  
    96.         byte[] keyBytes = decryptBASE64(publicKey);  
    97.   
    98.         // 构造X509EncodedKeySpec对象  
    99.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);  
    100.   
    101.         // ALGORITHM 指定的加密算法  
    102.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
    103.   
    104.         // 取公钥匙对象  
    105.         PublicKey pubKey = keyFactory.generatePublic(keySpec);  
    106.   
    107.         Signature signature = Signature.getInstance(keyFactory.getAlgorithm());  
    108.         signature.initVerify(pubKey);  
    109.         signature.update(data);  
    110.   
    111.         // 验证签名是否正常  
    112.         return signature.verify(decryptBASE64(sign));  
    113.     }  
    114.   
    115.     /** 
    116.      * 生成密钥 
    117.      *  
    118.      * @param seed 
    119.      *            种子 
    120.      * @return 密钥对象 
    121.      * @throws Exception 
    122.      */  
    123.     public static Map<String, Object> initKey(String seed) throws Exception {  
    124.         KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);  
    125.         // 初始化随机产生器  
    126.         SecureRandom secureRandom = new SecureRandom();  
    127.         secureRandom.setSeed(seed.getBytes());  
    128.         keygen.initialize(KEY_SIZE, secureRandom);  
    129.   
    130.         KeyPair keys = keygen.genKeyPair();  
    131.   
    132.         DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();  
    133.         DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();  
    134.   
    135.         Map<String, Object> map = new HashMap<String, Object>(2);  
    136.         map.put(PUBLIC_KEY, publicKey);  
    137.         map.put(PRIVATE_KEY, privateKey);  
    138.   
    139.         return map;  
    140.     }  
    141.   
    142.     /** 
    143.      * 默认生成密钥 
    144.      *  
    145.      * @return 密钥对象 
    146.      * @throws Exception 
    147.      */  
    148.     public static Map<String, Object> initKey() throws Exception {  
    149.         return initKey(DEFAULT_SEED);  
    150.     }  
    151.   
    152.     /** 
    153.      * 取得私钥 
    154.      *  
    155.      * @param keyMap 
    156.      * @return 
    157.      * @throws Exception 
    158.      */  
    159.     public static String getPrivateKey(Map<String, Object> keyMap)  
    160.             throws Exception {  
    161.         Key key = (Key) keyMap.get(PRIVATE_KEY);  
    162.   
    163.         return encryptBASE64(key.getEncoded());  
    164.     }  
    165.   
    166.     /** 
    167.      * 取得公钥 
    168.      *  
    169.      * @param keyMap 
    170.      * @return 
    171.      * @throws Exception 
    172.      */  
    173.     public static String getPublicKey(Map<String, Object> keyMap)  
    174.             throws Exception {  
    175.         Key key = (Key) keyMap.get(PUBLIC_KEY);  
    176.   
    177.         return encryptBASE64(key.getEncoded());  
    178.     }  
    179. }  



    再给出一个测试类:

    Java代码  收藏代码
    1. import static org.junit.Assert.*;  
    2.   
    3. import java.util.Map;  
    4.   
    5. import org.junit.Test;  
    6.   
    7. /** 
    8.  *  
    9.  * @author 梁栋 
    10.  * @version 1.0 
    11.  * @since 1.0 
    12.  */  
    13. public class DSACoderTest {  
    14.   
    15.     @Test  
    16.     public void test() throws Exception {  
    17.         String inputStr = "abc";  
    18.         byte[] data = inputStr.getBytes();  
    19.   
    20.         // 构建密钥  
    21.         Map<String, Object> keyMap = DSACoder.initKey();  
    22.   
    23.         // 获得密钥  
    24.         String publicKey = DSACoder.getPublicKey(keyMap);  
    25.         String privateKey = DSACoder.getPrivateKey(keyMap);  
    26.   
    27.         System.err.println("公钥: " + publicKey);  
    28.         System.err.println("私钥: " + privateKey);  
    29.   
    30.         // 产生签名  
    31.         String sign = DSACoder.sign(data, privateKey);  
    32.         System.err.println("签名: " + sign);  
    33.   
    34.         // 验证签名  
    35.         boolean status = DSACoder.verify(data, publicKey, sign);  
    36.         System.err.println("状态: " + status);  
    37.         assertTrue(status);  
    38.   
    39.     }  
    40.   
    41. }  


    控制台输出:

    Console代码  收藏代码
    1. 公钥:  
    2. MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp  
    3. RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn  
    4. xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE  
    5. C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ  
    6. FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo  
    7. g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv  
    8. 5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9  
    9. 21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=  
    10.   
    11. 私钥:  
    12. MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2  
    13. USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4  
    14. O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC  
    15. ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB  
    16. gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR  
    17. kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q  
    18.   
    19. 签名:  
    20. MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=  
    21.   
    22. 状态:  
    23. true  



    注意状态为true,就验证成功!

  • 相关阅读:
    元素绝对定位以后设置了高宽,a标签不能点击的原因总结
    SQL Server 索引结构及其使用(一)[转]
    【转】谈谈网页设计中的字体应用 (1) Font Set
    【转】 谈谈网页设计中的字体应用 (3) 实战应用篇·上
    SQL Server 索引结构及其使用(三)
    SQL Server 索引结构及其使用(二)
    SQL Server的复合索引学习【转载】
    【转】 谈谈网页设计中的字体应用 (4) 实战应用篇·下
    【转】谈谈网页设计中的字体应用 (2) serif 和 sansserif
    SQL Server 索引结构及其使用(四
  • 原文地址:https://www.cnblogs.com/kabi/p/6232926.html
Copyright © 2011-2022 走看看