java - 将 Java 转换为 python DSA 签名

标签 java python public-key-encryption dsa

有谁知道我如何将这个java代码转换为python?

/**
* signs the data for the account account
*/
private byte[] sign(String pkStr,byte[] data, String keyType) throws Exception {
    BASE64Decoder decoder = new BASE64Decoder();
    KeyFactory keyFac = null;
    //instantiate the key factory based on the key alg type
    if(keyType.equals("DSA")){
        keyFac = KeyFactory.getInstance("DSA");
    }else if(keyType.equals("RSA")){
        keyFac = KeyFactory.getInstance("RSA");
    }

    //generate the public key
    PKCS8EncodedKeySpec dprks = new PKCS8EncodedKeySpec(decoder.decodeBuffer(pkStr));
    PrivateKey pk = keyFac.generatePrivate(dprks);

    return(signBytes(data,pk,keyType));
}

    /**
* sign the data with the key
*/
private byte[] signBytes(byte [] data,
    PrivateKey signingPrivateKey, String keyType)throws Exception {

    Signature dsa = null;
    //instantiate the signature alg based on the key type
    if(keyType.equals("DSA")){
        dsa = Signature.getInstance("SHA1withDSA");
    }else if(keyType.equals("RSA")){
        dsa = Signature.getInstance("SHA1withRSA");
    }
    /* Initializing the object with a private key */
    dsa.initSign(signingPrivateKey);

    /* Update and sign the data */
    dsa.update(data);
    byte[] sig = dsa.sign();
    return sig;
}

“keyType”似乎总是作为“DSA”传递,所以我查看了 M2Crypto.DSA这看起来很有希望。然而,DSA.sign 函数返回一个 2 字节字符串的元组,我完全不确定如何处理它。

最佳答案

DSA 签名定义为一对整数(分别称为 rs)。 DSA standard不强制要求将此类签名特定编码为字节序列。因此,每个使用 DSA 签名的协议(protocol)都必须定义自己的编码。

常用的DSA签名编码有两种;一种是 rs 值的大端无符号编码的直接串联,两者都被标准化为 q< 的长度(以字节为单位)/em> 公钥中的参数(“子组大小”,通常是 160 位素数,从而产生 40 字节签名)。 M2Crypto.DSA 的文档非常简洁,但我的猜测是它分别返回 rs 但已经采用该格式。

Java 使用另一种编码,即基于 ASN.1 的编码。这是整个 X.509 以及基于它的任何内容(包括 SSL/TLS 中的签名)中使用的编码。 ASN.1 是结构化数据表示和序列化的通用标准。在这种情况下,签名应该是 ASN.1 SEQUENCE 的序列化。包含两个INTEGER值(rs,按顺序)。根据 ASN.1 和 DER 编码规则,签名应具有以下格式:

0x30 A 0x02 B R 0x02 C S

地点:

  • Rr 的大端有符号编码,具有最小长度:这意味着第一个字节应具有0 到 127 之间的值,并且仅当第二个字节的值介于 128 到 255 之间时,它才应具有值 0。换句话说,将 r 编码为具有大端约定的字节序列(最重要的字节首先出现),确保您有尽可能少的前导零位,前提是您至少保留一个(这就是“有符号”编码的含义:因为r是正数,它的最高有效位必须是 0)。由于r0q-1之间的整数,因此R的长度最多多1 byte 的长度大于 q 的长度,但可以更小。

  • Ss 的大端有符号编码(与 r 的处理方式相同;注意:R S可能有不同的长度)。

  • B 是包含 R 长度(以字节为单位)的单个字节。

  • C 是包含 S 长度(以字节为单位)的单个字节。

  • A 是包含 B+C+2 的单个字节(即字节 A 之后的长度,以字节为单位) em>)。

为基于 ASN.1 的 DSA 签名编写专门的编码和解码函数有点繁琐,但并不难;只需注意生成正确大小的 RS 序列即可。或者,您可以使用现有的 ASN.1 编码/解码库,这有点过头了,但可能更容易,具体取决于您的情况。

关于java - 将 Java 转换为 python DSA 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7068733/

相关文章:

ios - 从证书中获取公钥/私钥

java - Java 中基于 HTTPS 的 WSDL

java - 描述 资源路径 位置类型 与元素类型 "p"关联的属性 "p:sessionFactory-ref"的前缀 "beans:bean"未绑定(bind)

java - 从/src/main/resources 读取文件出现异常 FileNotFound

python | tkinter 和线程 : "main thread is not in main loop"

python - 输入和用户输入验证

python - 验证 ModelForm 的最佳方法

validation - 如何共享 OAuth2 JWT 验证的公钥?

ssl - 如何使用 OpenSSL 验证 GPG 签名

java - 水平 ScrollView 中的可用空间