我正在尝试实现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 hash的输出替换它,则私钥无法在PrivateKey实例中转换。
我经历了https://github.com/bcgit/bc-java/issues/251,https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-byte-to-32-byte-representation,https://crypto.stackexchange.com/questions/72134/raw-curve25519-public-key-points的净资源。
以上资源提出了Curve25519的Bouncy Castle解释私钥的方式,与某些互联网资源提出的方式不同。在帖子https://crypto.stackexchange.com/questions/51703/how-to-convert-from-curve25519-33-byte-to-32-byte-representation中,提及如下。
根据curve25519论文,x25519公钥可以表示为32个字节。
我正在使用的x25519库(bouncycastle)根据该标准为我提供了33个字节的表示形式。
我对ECC还是很陌生,这些资源使我感到困惑,长度之间的差异,大与小的编码风格。
我尝试了libSodium'crypto_box_easy'和'crypto_box_open_easy' 通过其Java绑定,一切正常。 32字节scrypt输出 由'crypto_box_seed_keypair'使用以生成密钥对 用于加密过程。
正如我所看到的,这里涉及一些我目前缺少的数学,或者我看不到转换。
我必须走这条路线Scrypt输出->密钥对->用于加密
可以直接使用来自BC的KeyGenerator,但这可以利用SecureRandom,但是我需要Scrypt的输出才能充当私钥。
问题:
我将非常感谢有人帮助我了解libSodium和Bouncy Castle方法之间的区别。 libSodium提到它使用X25519。当我尝试从32个字节创建X25519密钥时,但BC Cipher(ECIESwithAES-CBC)则抱怨它不是EC Point,从该资源“ https://github.com/bcgit/bc-java/issues/251”看来,这也存在差异(Curve25519与X25519 )。
私钥“ d”,如何解释。我在Bouncy Castle文档和测试用例中看到了这些随机值,这仅仅是有效密钥规定范围内的数字吗?在创建BigInteger实例之前,会处理此数字(小字节序与大字节序)。我的意思是我的代码示例中'd'的原始值是从其他数字转换而来的?
我对理解Curve25519的不同机制与BC API本身之间的斗争感到非常困惑。
一些进一步推动我的研究的指针将大有帮助。