美文网首页
【Java小工匠】数字签名-DSA

【Java小工匠】数字签名-DSA

作者: Java小工匠 | 来源:发表于2018-06-29 23:23 被阅读0次

    1、DSA数字签名概述

    1.1 DSA加密算算法

    DSA(Digital Signature Algorithm)是Schnorr和ElGamal签名算法的变种,被美国NIST作为数字签名标准(DigitalSignature Standard)。

    DSA(Digital Signature Algorithm,数字签名算法,用作数字签名标准的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。它也可用于由第三方去确定签名和所签数据的真实性。DSA算法的安全性基于解离散对数的困难性,这类签字标准具有较大的兼容性和适用性,成为网络安全体系的基本构件之一。

    2、DSA数字签名算法分类

    DSA只能与SHA-1一起使用。

    3、DSA数字签名实现

    3.1 JDK实现

    package lzf.cipher.jdk;
    
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    
    /**
     * @author java小工匠
     */
    public class JdkSignatureDsaUtils {
        public static final String DSA = "DSA";
        public static final String MD5withDSA = "SHAwithDSA";
    
        // 初始化密钥对
        public static KeyPair initKey() {
            try {
                KeyPairGenerator generator = KeyPairGenerator.getInstance(DSA);
                // 512 -65536 && 64 的倍数
                generator.initialize(1024);
                return generator.generateKeyPair();
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
        }
    
        // 获取公钥
        public static byte[] getPublicKey(KeyPair keyPair) {
            byte[] bytes = keyPair.getPublic().getEncoded();
            return bytes;
        }
    
        // 获取公钥
        public static String getPublicKeyStr(KeyPair keyPair) {
            byte[] bytes = keyPair.getPublic().getEncoded();
            return encodeHex(bytes);
        }
    
        // 获取私钥
        public static byte[] getPrivateKey(KeyPair keyPair) {
            byte[] bytes = keyPair.getPrivate().getEncoded();
            return bytes;
        }
    
        // 获取私钥
        public static String getPrivateKeyStr(KeyPair keyPair) {
            byte[] bytes = keyPair.getPrivate().getEncoded();
            return encodeHex(bytes);
        }
    
        // 签名
        public static byte[] sign(byte[] data, byte[] privateKey, String type) {
            try {
                // 还原使用
                PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
                KeyFactory keyFactory = KeyFactory.getInstance(DSA);
                PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
                // 1、实例化Signature
                Signature signature = Signature.getInstance(type);
                // 2、初始化Signature
                signature.initSign(priKey);
                // 3、更新数据
                signature.update(data);
                // 4、签名
                return signature.sign();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 验证
        public static boolean verify(byte[] data, byte[] publicKey, byte[] sign, String type) {
            try {
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
                KeyFactory keyFactory = KeyFactory.getInstance(DSA);
                PublicKey pubKey = keyFactory.generatePublic(keySpec);
                // 1、实例化Signature
                Signature signature = Signature.getInstance(type);
                // 2、初始化Signature
                signature.initVerify(pubKey);
                // 3、更新数据
                signature.update(data);
                // 4、签名
                return signature.verify(sign);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        // 数据准16进制编码
        public static String encodeHex(final byte[] data) {
            return encodeHex(data, true);
        }
    
        // 数据转16进制编码
        public static String encodeHex(final byte[] data, final boolean toLowerCase) {
            final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
            final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
            final int l = data.length;
            final char[] out = new char[l << 1];
            // two characters form the hex value.
            for (int i = 0, j = 0; i < l; i++) {
                out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
                out[j++] = toDigits[0x0F & data[i]];
            }
            return new String(out);
        }
    
        public static void main(String[] args) {
            String str = "java小工匠";
            byte[] data = str.getBytes();
            // 初始化密钥度
            KeyPair keyPair = initKey();
            byte[] publicKey = getPublicKey(keyPair);
            byte[] privateKey = getPrivateKey(keyPair);
            // 签名
            String type = MD5withDSA;
            byte[] sign = sign(str.getBytes(), privateKey, type);
            // 验证
            boolean b = verify(data, publicKey, sign, type);
            System.out.println("验证:" + b);
        }
    }
    

    如果读完觉得有收获的话,欢迎点赞、关注、加公众号【小工匠技术圈】

    个人公众号,欢迎关注,查阅更多精彩历史!

    image

    相关文章

      网友评论

          本文标题:【Java小工匠】数字签名-DSA

          本文链接:https://www.haomeiwen.com/subject/gxdweftx.html