9

我正在开发分布式数字签名,它对文档进行签名并通过网络将其发送到应用程序服务器。我正在使用 java 中的套接字编程来做到这一点。我认为应该对公钥进行编码或压缩,即 x 和 y 值以某种方式表示为单个二进制数据并保存在公共注册表或网络中。但我不知道如何在 java 中做到这一点。

        // I have class like this 
           public class CryptoSystem{                  

               EllipticCurve ec = new EllipticCurve(new P192());

               //-------------------
               //--------------------

               public ECKeyPair generatekeyPair()
               {
                  return ECKeyPair(ec);

               }


            }    
        // i don't think i have problem in the above


    CryptoSystem crypto = new CryptoSystem();
    ECKeyPair keyPair = crypto.generateKeyPair();
    BigInteger prvKey = keyPair.getPrivateKey();
    ECPoint pubKey = keyPair.getPublicKey();
     // recommend me here to  compress and send it  the public key to a shared network.

我想知道如何对公钥和域参数进行编码,以便签名的验证者对其进行解码以使用它。因为当您通过网络将它们发送给验证者时,您必须将其编码为单字节数组.我没有使用 Bouncy Castle Provider。ECDSA算法的整个实现是我的项目

4

2 回答 2

11

椭圆曲线点几乎总是使用 X9.62 中指定的编码进行编码。

使用点压缩是可选的。使用点压缩进行编码很简单,但是解码压缩点需要更多的工作,所以除非你真的需要保存额外的字节,否则我不会打扰。如果您需要,请告诉我,我会添加详细信息。您可以通过第一个字节(即 0x02 或 0x03)点压缩来识别 X9.62 编码点。

没有点压缩的编码非常简单:以 0x04 开头(表示不压缩)。然后首先是 x 坐标,然后是 y 坐标,在左侧都用零填充,直到字段的大小(以字节为单位):

int qLength = (q.bitLength()+7)/8;
byte[] xArr = toUnsignedByteArray(x);
byte[] yArr = toUnsignedByteArray(y);
byte[] res = new byte[1+2*qLength];
res[0] = 0x04;
System.arraycopy(xArr, 0, res, qLength - xArr.length, xArr.length);
System.arraycopy(yArr, 0, res, 2* qLength - yArr.length, nLength);

解码这当然是微不足道的。

于 2012-06-07T20:53:12.770 回答
4

我很确定 BC 实现使用 X9.63 编码,所以这些将是相当标准化的编码。您需要将 Bouncy Castle 提供程序添加到您的 JRE ( Security.addProvider(new BouncyCastleProvider()),请参阅 bouncy 文档。

public static void showECKeyEncodings() {

    try {
        KeyPairGenerator kp = KeyPairGenerator.getInstance("ECDSA");
        ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable
                .getParameterSpec("prime192v1");
        kp.initialize(ecSpec);
        KeyPair keyPair = kp.generateKeyPair();

        PrivateKey privKey = keyPair.getPrivate();
        byte[] encodedPrivKey = privKey.getEncoded();
        System.out.println(toHex(encodedPrivKey));

        PublicKey pubKey = keyPair.getPublic();
        byte[] encodedPubKey = pubKey.getEncoded();
        System.out.println(toHex(encodedPubKey));

        KeyFactory kf = KeyFactory.getInstance("ECDSA");
        PublicKey pubKey2 = kf.generatePublic(new X509EncodedKeySpec(encodedPubKey));
        if (Arrays.equals(pubKey2.getEncoded(), encodedPubKey)) {
            System.out.println("That worked for the public key");
        }

        PrivateKey privKey2 = kf.generatePrivate(new PKCS8EncodedKeySpec(encodedPrivKey));
        if (Arrays.equals(privKey2.getEncoded(), encodedPrivKey)) {
            System.out.println("That worked for the private key");
        }

    } catch (GeneralSecurityException e) {
        throw new IllegalStateException(e);
    }

}
于 2012-06-08T01:51:01.603 回答