Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Java转换为python DSA签名_Java_Python_Public Key Encryption_Dsa - Fatal编程技术网

将Java转换为python DSA签名

将Java转换为python DSA签名,java,python,public-key-encryption,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; //instanti

有人知道我将如何将这个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”,所以我已经看过了,这看起来很有希望。然而,DSA.sign函数返回一个由2字节字符串组成的元组,我根本不知道如何处理它。

根据(出于某些奇怪的原因,它有两个附录B,您需要向下滚动到第二个附录B),Java使用ASN.1编码
序列::={r INTEGER,s INTEGER}

您应该能够使用pyasn1-


ASN.1是编码二进制数据的标准。因此,上面的信息指定了Java代码如何组合Python代码返回的两个值。因此,您可以执行相同的操作,从而保持签名的相同字节格式。

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

有两种常用的DSA签名编码;一种是r和s值的大端无符号编码的直接串联,两者都被规范化为公钥中q参数的长度(以字节为单位)(“子组大小”,通常是160位的素整数,因此产生40字节的签名)。M2Crypto.DSA的文档非常简洁,但我猜它分别返回r和s,但已经是那种格式了

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

0x30 A 0x02 B R 0x02 C S

其中:

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

  • S是S的大端有符号编码(与r的处理相同;注意:r和S可能有不同的长度)

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

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

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


为基于ASN.1的DSA签名编写专门的编码和解码函数有点乏味,但并不难;只需注意生成大小合适的R和S序列。或者,您也可以使用现有的ASN.1编码/解码库,这可能有些过火,但可能更容易,具体取决于您的情况。

我的答案不正确有什么原因吗?很抱歉,我没有接受这个问题的答案。这个python项目被暂时搁置。尽管如此,我还是对答案投了赞成票,因为它似乎把我带向了正确的方向。当我重新开始这个项目时,我会回来接受答案。