将Java转换为python DSA签名
有人知道我将如何将这个java代码转换成python吗将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
/**
* 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项目被暂时搁置。尽管如此,我还是对答案投了赞成票,因为它似乎把我带向了正确的方向。当我重新开始这个项目时,我会回来接受答案。