有谁知道如何将这个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字节字符串的元组,我不知道该怎么做。
答案 0 :(得分:3)
DSA签名被定义为一对整数(分别称为 r 和 s )。 DSA standard不要求将这种签名的特定编码强制为字节序列。因此,使用DSA签名的每个协议都必须定义自己的编码。
有两种常用的DSA签名编码;一个是 r 和 s 值的大端无符号编码的直接串联,两者都被归一化为 q <的长度(以字节为单位) / em>公钥中的参数(“子组大小”,通常是160位素数整数,因此产生40字节的签名)。 M2Crypto.DSA的文档非常简洁,但我的猜测是它分别返回 r 和 s ,但已经采用该格式。
Java使用其他编码,即基于ASN.1。这是整个X.509中使用的编码以及基于它的任何内容(包括SSL / TLS中的签名)。 ASN.1是结构化数据表示和序列化的通用标准。在这种情况下,签名应该是包含两个SEQUENCE
值( r 和 s )的ASN.1 INTEGER
的序列化,按顺序)。根据ASN.1和DER编码规则,签名应具有以下格式:
0x30 A 0x02 B R 0x02 C S
其中:
R 是 r 的big-endian 签名编码,长度最小:这意味着第一个字节应该有0到127之间的值,仅当第二个字节的值介于128和255之间时,它才应为0。换句话说,将 r 编码为具有big-endian约定的字节序列(最重要的字节是第一个),确保你有尽可能少的前导零位,前提是你保留至少一个(这是“签名”编码的意思:因为 r 是正数,其最重要的位必须为0)。由于 r 是 0 和 q-1 之间的整数,因此 R 的长度最多为一个字节大于 q 的长度,但它可以更小。
S 是 s 的big-endian签名编码(与 r 相同的处理方式;注意: R 和 S 可能有不同的长度。)
B 是一个包含 R 长度的单字节(以字节为单位)。
C 是一个包含 S 长度的单字节(以字节为单位)。
是包含 B + C + 2 的单字节(即字节 A 后面的长度,以字节为单位) EM>)。
为基于ASN.1的DSA签名编写专门的编码和解码功能有点乏味但并不难;只需要处理正确大小的 R 和 S 序列。或者,您可以使用现有的ASN.1编码/解码库,这可能更容易,但可能更容易,具体取决于您的情况。
答案 1 :(得分:1)
根据http://download.oracle.com/javase/1.5.0/docs/guide/security/CryptoSpec.html#AppB(出于某些奇怪的原因,有两个附录B,你需要向下滚动到第二个),Java使用ASN.1编码SEQUENCE ::= { r INTEGER, s INTEGER }
你应该能够使用pyasn1在Python中生成(和解析) - http://pyasn1.sourceforge.net/
ASN.1是编码二进制数据的标准。因此,上面的信息指定了Java代码如何组合Python代码返回的两个值。因此,您可以这样做,因此保持签名的相同字节格式。