問題描述
我有一個使用 MSRCrypto 簽署我的 nonce 的服務(wù)器.我需要在 Java 中驗證隨機(jī)數(shù).眾所周知,MSRCrypto 以 P1363 格式發(fā)送它,Java 庫要求它以 DER 格式發(fā)送.
I have a server which uses MSRCrypto to sign my nonce. I need to verify that nonce in Java. It is well know that MSRCrypto sends it in P1363 format and Java Library requires it in DER format.
由于我是客戶端,我無法更改服務(wù)器代碼.服務(wù)器正在使用 SHA386withECDSA
I cannot change the server code as I am the client. The server is using SHA386withECDSA
1) 誰能給我提供準(zhǔn)確的代碼片段,以便在 Java 中將其從 P1363 格式轉(zhuǎn)換為 ASN.1,反之亦然(ASN.1 到 P1363).我嘗試了一些代碼片段,但無法使其工作(因為這些片段是用 C、C++ 編寫的).
1) Can someone provide me with exact code snippet to convert it from P1363 format to ASN.1 and vice-versa(ASN.1 to P1363) in Java. I tried a few code snippets but was not able to make it work (because those snippets were in C, C++).
2) 是否有一個庫可以用來進(jìn)行這些轉(zhuǎn)換而無需自己編寫.Bouncy Castle 是否提供此功能?
2) Is there a library which I can use to do these conversion without writing it myself. Like does Bouncy Castle provide this?
我也知道我可以將 BouncyCastle 與 SHAXwithPLAIN-ECDSA
或 SHAXwithCVC-ECDSA
一起使用.然而,Bouncy Castle/Spongy Castle 在 Android 上運(yùn)行時會很慢,因為它不進(jìn)行本地調(diào)用.Java 9 也提供該支持,但我仍在使用 Java 8.
I am also aware that I can use BouncyCastle with SHAXwithPLAIN-ECDSA
or with SHAXwithCVC-ECDSA
. However Bouncy Castle/ Spongy Castle is slow when running this on Android because it does not do native calls. The support is also available in Java 9 but I am still using Java 8.
推薦答案
BouncyCastle 沒有將一種簽名格式直接轉(zhuǎn)換為另一種的功能.它確實有一個通用的 ASN.1 編碼/解碼庫(對于 DER 和 BER,盡管加密幾乎完全使用 DER)可以處理 ASN.1 的一半,但你仍然需要做普通"(P1363,CVC,PKCS11,Microsoft)一半,在輸入(解碼)端非常容易,但在輸出(編碼)端卻有點困難.對于這種格式,您需要知道并使用曲線順序的八位字節(jié)大小(或者更準(zhǔn)確地說是生成器和子組順序,有時與基礎(chǔ)曲線不同),我在這里稱之為 n.
BouncyCastle doesn't have a facility to directly convert one signature format to the other. It does have a general-purpose ASN.1 encoding/decoding library (for both DER and BER, although crypto uses almost entirely DER) which can handle the ASN.1 half, but you still have to do the 'plain' (P1363, CVC, PKCS11, Microsoft) half, which is dead easy on the input (decode) side but a little harder on the output (encode) side. For that format you need to know and use the size in octets of the curve order (or more exactly the generator and subgroup order, which sometimes differs from the underlying curve), which I call n here.
我展示了非常有限的錯誤處理,包括拋出一個無意義的異常并讓 JVM 顯示它.在真正的程序中,您會希望做得更好,但您想做的事情會有所不同.
I show very limited error handling, consisting of throwing an uninformative Exception and letting the JVM display it. In a real program you will want to do better, but what you will want to do varies.
static void SO61860104Convert1 (String[] args) throws Exception {
int n = 32; // for example assume 256-bit-order curve like P-256
byte[] plain = Files.readAllBytes(Paths.get(args[0]));
// common
BigInteger r = new BigInteger (+1, Arrays.copyOfRange(plain,0,n));
BigInteger s = new BigInteger (+1, Arrays.copyOfRange(plain,n,n*2));
// with BouncyCastle
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r)); v.add(new ASN1Integer(s));
Files.write(Paths.get(args[1]), new DERSequence(v) .getEncoded() );
// without
byte[] x1 = r.toByteArray(), x2 = s.toByteArray();
// already trimmed two's complement, as DER wants
int len = x1.length + x2.length + (2+2), idx = len>=128? 3: 2;
// the len>=128 case can only occur for curves of 488 bits or more,
// and can be removed if you will definitely not use such curve(s)
byte[] out = new byte[idx+len]; out[0] = 0x30;
if( idx==3 ){ out[1] = (byte)0x81; out[2] = (byte)len; } else { out[1] = (byte)len; }
out[idx] = 2; out[idx+1] = (byte)x1.length; System.arraycopy(x1, 0, out, idx+2, x1.length);
idx += x1.length + 2;
out[idx] = 2; out[idx+1] = (byte)x2.length; System.arraycopy(x2, 0, out, idx+2, x2.length);
Files.write(Paths.get(args[2]), out);
}
static void SO61860104Convert2 (String[] args) throws Exception {
int n = 32; // for example assume 256-bit-order curve like P-256
byte[] der = Files.readAllBytes(Paths.get(args[0]));
BigInteger r, s;
byte[] out;
// with BouncyCastle
ASN1Sequence seq = ASN1Sequence.getInstance(der);
r = ((ASN1Integer)seq.getObjectAt(0)).getValue();
s = ((ASN1Integer)seq.getObjectAt(1)).getValue();
// common output
out = new byte[2*n]; toFixed(r, out, 0, n); toFixed(s, out, n, n);
Files.write(Paths.get(args[1]), out);
// without
if( der[0] != 0x30 ) throw new Exception();
int idx = der[1]==0x81? 3: 2; // the 0x81 case only occurs for curve over 488 bits
if( der[idx] != 2 ) throw new Exception();
r = new BigInteger (1, Arrays.copyOfRange(der, idx+2, idx+2+der[idx+1]));
idx += der[idx+1] + 2;
if( der[idx] != 2 ) throw new Exception();
s = new BigInteger (1, Arrays.copyOfRange(der, idx+2, idx+2+der[idx+1]));
if( idx + der[idx+1] + 2 != der.length ) throw new Exception();
// common output
out = new byte[2*n]; toFixed(r, out, 0, n); toFixed(s, out, n, n);
Files.write(Paths.get(args[2]), out);
}
static void toFixed (BigInteger x, byte[] a, int off, int len) throws Exception {
byte[] t = x.toByteArray();
if( t.length == len+1 && t[0] == 0 ) System.arraycopy (t,1, a,off, len);
else if( t.length <= len ) System.arraycopy (t,0, a,off+len-t.length, t.length);
else throw new Exception();
}
這篇關(guān)于使用 Java 將 P1363 格式轉(zhuǎn)換為 ASN.1/DER 格式的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!