将Java转换为python DSA签名

2024-09-30 16:19:58 发布

您现在位置:Python中文网/ 问答频道 /正文

有人知道我将如何将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,这看起来很有前途。这个数字签名但是,函数返回一个由2字节字符串组成的元组,我根本不知道该如何处理。在


Tags: thekeydatastringifbyteprivatesign
2条回答

根据http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#AppB(出于某种奇怪的原因,它有两个附录B,您需要向下滚动到第二个),Java使用ASN.1编码SEQUENCE ::= { r INTEGER, s INTEGER }

您应该能够使用pyasn1-http://pyasn1.sourceforge.net/在Python中生成(并解析)这个

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

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

有两种常用的DSA签名编码;一种是直接串联rs值的大端无符号编码,它们都规范化为公钥中的q参数的长度(以字节为单位)(“子组大小”,通常是一个160位素数整数,从而产生一个40字节的签名)。M2文件加密DSA非常简洁,但我猜它会分别返回rs,但已经是这种格式了。在

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

0x30A0x02B R0x02C S

其中:

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

  • SS的大端有符号编码(与r的处理相同;注:rS可能有不同的长度)。

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

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

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

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

相关问题 更多 >