0

我正在尝试实现 ECIES 加密,下面的代码正在工作。

X9ECParameters ecP = CustomNamedCurves.getByName("curve25519");
ECParameterSpec ecSpec = EC5Util.convertToSpec(ecP);

BigInteger d = new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990");

ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec(
                    d, // d
                    ecSpec);
ECPoint Q = new FixedPointCombMultiplier().multiply(params.getG(), d.multiply(BigInteger.valueOf(-1)));

Q = Q.normalize();

ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(
                    new ECPoint(Q.getAffineXCoord().toBigInteger(), Q.getAffineYCoord().toBigInteger()), // Q
                    ecSpec);

KeyFactory factTrial = KeyFactory.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
BCECPrivateKey          sKey = (BCECPrivateKey) factTrial.generatePrivate(priKeySpec);
PublicKey           vKey = factTrial.generatePublic(pubKeySpec);

Cipher c = Cipher.getInstance("ECIESwithAES-CBC",BouncyCastleProvider.PROVIDER_NAME);
byte[] encodeBytes = c.doFinal(data.getBytes());
String encrypt = Base64.getEncoder().encodeToString(encodeBytes);

Cipher c2 = Cipher.getInstance("ECIESwithAES-CBC",BouncyCastleProvider.PROVIDER_NAME);
c2.init(Cipher.DECRYPT_MODE,sKey, c.getParameters()); 
byte[] decodeBytes = c2.doFinal(encodeBytes);
String deCrypt = new String(decodeBytes,"UTF-8");

问题是私钥元素“d”。如果我尝试用 scrypt 哈希的输出替换它,私钥无法在 PrivateKey 实例中转换。

我浏览了网络资源https://github.com/bcgit/bc-java/issues/251https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-字节到 32 字节表示https://crypto.stackexchange.com/questions/72134/raw-curve25519-public-key-points

以上资源表明 Curve25519 的 Bouncy Castle 解释私钥的方式与某些 Internet 资源建议的方式不同。在帖子https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-byte-to-32-byte-representation中提到如下。

根据 curve25519 论文,x25519 公钥可以用 32 个字节表示。

我正在使用的 x25519 库(bouncycastle)根据这个标准给了我一个 33 字节的表示。

我对 ECC 很陌生,这些资源让我很困惑,长度之间的差异,编码风格 big vs. little。

我已经通过其 Java 绑定尝试了 libSodium 'crypto_box_easy' 和 'crypto_box_open_easy' 并且一切正常。'crypto_box_seed_keypair' 使用 32 字节的 scrypt 输出来生成用于加密过程的密钥对。

正如我看到的,这里涉及到一些我目前缺乏的数学,或者我看不到转换。

我必须走这条路线 Scrypt 输出 -> 密钥对 -> 用于加密

直接使用来自 BC 的 KeyGenerator 是可行的,但它使用 SecureRandom,但我需要 Scrypt 的输出作为私钥。

问题:

  1. 我非常感谢有人帮助我理解 libSodium 和 Bouncy Castle 方法之间的区别。libSodium 提到它使用 X25519。当我尝试从 32 字节创建 X25519 密钥,但 BC 密码(ECIESwithAES-CBC)然后抱怨它不是 EC 点,来自此资源' https://github.com/bcgit/bc-java/issues/251 '似乎也存在差异(Curve25519 vs X25519)。

  2. 私钥'd',如何解释。我在 Bouncy Castle 文档和测试用例中看到了这些随机值,这仅仅是有效密钥规定范围内的数字吗?在创建 BigInteger 实例之前,会处理这个数字(小端与大端)。我的意思是我的代码示例中“d”的原始值是从其他数字转换而来的?

理解 Curve25519 的不同机制和 BC API 本身之间的斗争,我真的很困惑。

一些对我进一步研究的指导会很有帮助。

4

0 回答 0