使用Java将P1363格式转换为ASN

使用Java将P1363格式转换为ASN

本文介绍了使用Java将P1363格式转换为ASN.1 / DER格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一台使用MSRCrypto签名我的随机数的服务器。我需要验证Java中的随机数。众所周知,MSRCrypto以P1363格式发送它,而Java库要求以DER格式发送它。

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.

我不能更改服务器代码,因为我是客户端。服务器正在使用 SHA386withECDSA

I cannot change the server code as I am the client. The server is using SHA386withECDSA

1)有人可以在 Java 中为我提供准确的代码段,以将其从P1363格式转换为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)是否有一个我可以用来进行这些转换而无需自己编写的库。

2) Is there a library which I can use to do these conversion without writing it myself. Like does Bouncy Castle provide this?

我也知道我可以使用带有 SHAXwithPLAIN-ECDSA 或带有 SHAXwithCVC-ECDSA 的BouncyCastle。但是,Bouncy Castle / Spongy Castle在Android上运行时速度较慢,因为它不进行本地调用。 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无法直接使用将一种签名格式转换为另一种。它确实有一个通用的ASN.1编码/解码库(用于DER和BER,尽管加密几乎全部使用DER),它可以处理ASN.1的一半,但是您仍然必须执行普通操作(P1363, CVC,PKCS11,Microsoft)一半,这在输入(解码)端很容易实现,但是在输出(编码)端却有点困难。对于这种格式,您需要知道并使用八位位组的曲线顺序大小(或更确切地说,是生成器和子组顺序,有时与基础曲线不同),在这里我将其称为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();
}

这篇关于使用Java将P1363格式转换为ASN.1 / DER格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 12:58