Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何压缩或编码椭圆曲线公钥并将其放到网络上?_Java_Cryptography_Elliptic Curve - Fatal编程技术网

Java 如何压缩或编码椭圆曲线公钥并将其放到网络上?

Java 如何压缩或编码椭圆曲线公钥并将其放到网络上?,java,cryptography,elliptic-curve,Java,Cryptography,Elliptic Curve,我正在开发分布式数字签名,对文档进行签名,并通过网络将其发送到应用服务器。我正在使用java中的socket编程来实现这一点。我认为公钥应该进行编码或压缩,即x和y值以某种方式表示为单个二进制数据,并保存在公共注册表或网络中。但我不知道如何在java中实现这一点 // I have class like this public class CryptoSystem{ EllipticCur

我正在开发分布式数字签名,对文档进行签名,并通过网络将其发送到应用服务器。我正在使用java中的socket编程来实现这一点。我认为公钥应该进行编码或压缩,即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算法的整个实现是我的项目

椭圆曲线点几乎总是使用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);

解码这当然很简单。

我很确定BC实现使用了X9.63编码,因此这些编码相当标准化。您需要将Bouncy Castle提供程序添加到JRE(
Security.addProvider(新的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);
    }

}

如何在内存中表示它们?它们只是大整数,序列化应该很容易。是否要使用点压缩?这是一种只序列化x坐标和y坐标的符号,然后使用曲线方程恢复y坐标的技术。是的,除了压缩之外,我还想将压缩在共享网络注册表中设置公钥,以便两个或多个应用程序服务器将使用它来验证签名。您使用的API是什么?例如,crypto实例和ECKeyPair类的FQN类名是什么?尽管如前所述,您可以检索BigInteger值并按原样存储。crypto实例的类是我自己的。谢谢,我理解nd ur答案。我应该将公钥保存在哪里,以便远程区域上的一个或多个应用程序服务器使用?域参数(q、a、b、G、n、h)如何,它们如何传递到远程签名验证应用程序,因为存在动态选择椭圆曲线作为u形签名的应用程序。p-192,p-224,…,p-512建议的椭圆曲线域parameters@Clickmit:我假设您有静态域参数,并且只是在每一端硬编码它们。如果您只有一小部分受支持的曲线,我会st做一些事情,比如在一个整数前面加上一个前缀,指定使用的是哪条曲线。如果要对所有域参数进行编码,也有相应的标准(查找ECDomainParameters ASN.1结构),但我认为你应该为此找到一个ASN.1阶编码器。手工编码这种结构的编码并不简单。是否可以添加用于处理压缩密钥的过程?能否请你帮助解码压缩点?——@RasmusFaber在这种情况下,我恳请你看看非常宽容的基本Bouncy Castle im实现,如果不是为了复制,那么只需查看域参数的标准X9.62编码。BSI TR-03111还有一种(更简单的)域参数编码方法。这个示例似乎也适用于JDK 1.8,只是需要将“EC”传递给KeyPairGenerator和KeyFactory。另外,“prime192v1”需要替换为“secp192r1”在JDK 1.8中。@kravietz是的,您还需要对密钥对生成器使用
ECGenParameterSpec
。我将编辑答案以尽快反映这些更改。有趣的是,BC和Oracle编码不同;私钥包含(可选)对于Oracles的ASN.1编码,公钥不适用于BC。因此两者都是正确的和兼容的,只是略有不同。@K.Os请不要这样做。这是团队的努力,我这里不提供个人建议。