有谁知道我如何将这个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 签名定义为一对整数(分别称为 r 和 s)。 DSA standard不强制要求将此类签名特定编码为字节序列。因此,每个使用 DSA 签名的协议(protocol)都必须定义自己的编码。
常用的DSA签名编码有两种;一种是 r 和 s 值的大端无符号编码的直接串联,两者都被标准化为 q< 的长度(以字节为单位)/em> 公钥中的参数(“子组大小”,通常是 160 位素数,从而产生 40 字节签名)。 M2Crypto.DSA 的文档非常简洁,但我的猜测是它分别返回 r 和 s 但已经采用该格式。
Java 使用另一种编码,即基于 ASN.1 的编码。这是整个 X.509 以及基于它的任何内容(包括 SSL/TLS 中的签名)中使用的编码。 ASN.1 是结构化数据表示和序列化的通用标准。在这种情况下,签名应该是 ASN.1 SEQUENCE
的序列化。包含两个INTEGER
值(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的长度最多多1 byte 的长度大于 q 的长度,但可以更小。
S 是 s 的大端有符号编码(与 r 的处理方式相同;注意:R 和S可能有不同的长度)。
B 是包含 R 长度(以字节为单位)的单个字节。
C 是包含 S 长度(以字节为单位)的单个字节。
A 是包含 B+C+2 的单个字节(即字节 A 之后的长度,以字节为单位) em>)。
为基于 ASN.1 的 DSA 签名编写专门的编码和解码函数有点繁琐,但并不难;只需注意生成正确大小的 R 和 S 序列即可。或者,您可以使用现有的 ASN.1 编码/解码库,这有点过头了,但可能更容易,具体取决于您的情况。
关于java - 将 Java 转换为 python DSA 签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7068733/