4.3 DSA数字签名技术

数字签名技术 -- DSA算法

DSA算法是1991年美国国家标准技术协会公布的数字签名标准(DSS)的核心算法。DSA算法本质是ElGamal数字签名算法,仅能与SHA系列算法结合,没有相应的MD融合算法。

DSA算法和RSA算法的异同

DSA算法是DSS技术的核心算法,与RSA算法的异同如下:

  • 二者都是数字签名算法中的重要组成,缺一不可;
  • DSA算法仅仅包含数字签名算法,一般不用于加密算法中;
  • DSA算法仅产生数字证书,信息仅能用于验证,不适合进行加密通信,所以HTTPS不会使用这个算法;
  • RSA算法包含加解密的密钥信息,同时可作为数字签名算法;

下面是一段DSA和RSA的不同的比较原文,可以参考下:

The main difference is in RSA ,message hash value is generated then this hash value is encryption using sender's private key this is treated as a signature and this signature is pretended with message .then receiver side perform decryption using sender's public key and this compare with new hash value that are generate by msg if both are same then msg is accepted otherwise rejected.

But in DSS approach additional add a signing algorithm that take input as a hash value of msg,random key ,global public key and sender's private key then the output is pretended to the msg . at receiver side pass the result (output), signature and msg, as well as global public key using this four take as the input of verification function then output of verification function is compare with result. The main difference is in RSA compare with hash value other hand in DSS output of verification is compare with result.

算法基本流程

  • 发送方:使用信息摘要算法对原始数据计算摘要
  • 发送方:产生一个随机数,将摘要信息、随机数私钥全局公钥(不是私钥对应的公钥)传入到算法中;
  • 发送方:算法计算一个签名串,将签名串和原始数据一起传输;
  • 接收方:对原始数据计算摘要
  • 接收方:将接受到的签名串发送给验证函数,验证函数使用发送方公钥全局公钥来比较验证签名信息;

算法家族

包含:SHA1withDSASHA224withDSASHA256withDSASHA384withDSASHA512withDSA五种算法。

密钥长度都是512-1024位。

Java中的算法实现

JDK实现了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));
    }

}

你可能感兴趣的:(4.3 DSA数字签名技术)