数字签名技术 -- DSA算法

37 篇文章 0 订阅
13 篇文章 0 订阅

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

DSA算法和RSA算法的异同

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

  • 二者都是数字签名算法中的重要组成,缺一不可;
  • DSA算法仅仅包含数字签名算法,没有密钥信息;
  • DSA算法产生的数字证书无法进行加密通信,HTTPS不会使用这个算法;
  • RSA算法包含加解密的密钥信息,同时又数字签名算法的作用;

算法家族

包含:SHA1withDSA、SHA224withDSA、SHA256withDSA、SHA384withDSA、SHA512withDSA五种算法。

密钥长度都是512-1024位。

Java中的算法实现

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

}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DSA(Digital Signature Algorithm)数字签名算法是一种公钥密码学算法,可以用于数字签名和身份认证。下面是一个简单的C++实现。 首先,需要引入openssl库,可以使用以下命令安装: ``` sudo apt-get install libssl-dev ``` 然后,可以使用以下代码生成DSA密钥对: ```cpp #include <openssl/dsa.h> #include <openssl/engine.h> #include <openssl/rand.h> void generate_dsa_keypair(DSA *&dsa, int bits) { // 随机数种子初始化 RAND_load_file("/dev/urandom", 1024); // 创建DSA密钥对 dsa = DSA_new(); DSA_generate_parameters_ex(dsa, bits, NULL, 0, NULL, NULL, NULL); DSA_generate_key(dsa); } ``` 接下来,可以使用以下代码对数据进行签名: ```cpp void dsa_sign(const unsigned char *data, size_t data_len, DSA *dsa, unsigned char *sig, unsigned int *sig_len) { // 创建DSA上下文 DSA_SIG *dsa_sig = DSA_do_sign(data, data_len, dsa); // 将签名结果写入到sig中 *sig_len = i2d_DSA_SIG(dsa_sig, &sig); DSA_SIG_free(dsa_sig); } ``` 最后,可以使用以下代码对签名进行验证: ```cpp bool dsa_verify(const unsigned char *data, size_t data_len, const unsigned char *sig, size_t sig_len, DSA *dsa) { // 将签名结果解析成DSA_SIG结构 DSA_SIG *dsa_sig = d2i_DSA_SIG(NULL, &sig, sig_len); // 验证签名 bool result = DSA_do_verify(data, data_len, dsa_sig, dsa); DSA_SIG_free(dsa_sig); return result; } ``` 完整的代码如下: ```cpp #include <openssl/dsa.h> #include <openssl/engine.h> #include <openssl/rand.h> void generate_dsa_keypair(DSA *&dsa, int bits) { // 随机数种子初始化 RAND_load_file("/dev/urandom", 1024); // 创建DSA密钥对 dsa = DSA_new(); DSA_generate_parameters_ex(dsa, bits, NULL, 0, NULL, NULL, NULL); DSA_generate_key(dsa); } void dsa_sign(const unsigned char *data, size_t data_len, DSA *dsa, unsigned char *sig, unsigned int *sig_len) { // 创建DSA上下文 DSA_SIG *dsa_sig = DSA_do_sign(data, data_len, dsa); // 将签名结果写入到sig中 *sig_len = i2d_DSA_SIG(dsa_sig, &sig); DSA_SIG_free(dsa_sig); } bool dsa_verify(const unsigned char *data, size_t data_len, const unsigned char *sig, size_t sig_len, DSA *dsa) { // 将签名结果解析成DSA_SIG结构 DSA_SIG *dsa_sig = d2i_DSA_SIG(NULL, &sig, sig_len); // 验证签名 bool result = DSA_do_verify(data, data_len, dsa_sig, dsa); DSA_SIG_free(dsa_sig); return result; } int main() { // 生成DSA密钥对 DSA *dsa; generate_dsa_keypair(dsa, 1024); // 要签名的数据 unsigned char data[] = "hello world"; size_t data_len = sizeof(data) - 1; // 对数据进行签名 unsigned char sig[1024]; unsigned int sig_len; dsa_sign(data, data_len, dsa, sig, &sig_len); // 验证签名 bool result = dsa_verify(data, data_len, sig, sig_len, dsa); if (result) { std::cout << "signature verified" << std::endl; } else { std::cout << "signature verification failed" << std::endl; } DSA_free(dsa); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值