从Bouncy Castle Java获取原始密钥



我正在使用ECDSA的C和Java实现。C实现使用原始格式——32字节私钥、64字节公钥、64字节签名。

我正在使用Bouncy Castle:在Java中创建密钥

public static KeyPair GenerateKeys() throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ecSpec, new SecureRandom());
return g.generateKeyPair();
}

并希望将它们存储为字节数组,因为我稍后需要将它们导出到我的C应用程序

KeyPair vendorKeys = GenerateKeys();
for (byte byt : vendorKeys.getPublic().getEncoded()) {
System.out.println("byt: " +  byt);
}

将返回公钥的字节,但长度错误。我想这和PublicKey的X.509和private的PKCS#8格式有关。在寻求帮助时,我发现Java中有一些类,比如PKCS8EncodedKeySpec,应该可以帮助我获得原始密钥,但我不知道如何做到这一点。

私钥或公钥的x和y坐标可以通过BouncyCastle的实现ECPrivateKeyECPublicKey来确定。使用getD()可以确定私钥,使用getQ()可以确定公钥,例如:

import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;
...
ECPublicKey publickKey = (ECPublicKey)vendorKeys.getPublic();
ECPrivateKey privateKey = (ECPrivateKey)vendorKeys.getPrivate();
byte[] rawPrivate = BigIntegers.asUnsignedByteArray(privateKey.getD());
byte[] x = publickKey.getQ().getAffineXCoord().getEncoded();
byte[] y = publickKey.getQ().getAffineYCoord().getEncoded();        
byte[] rawPublic = ByteBuffer.allocate(x.length + y.length).put(x).put(y).array();
System.out.println(Hex.toHexString(rawPrivate));
System.out.println(Hex.toHexString(rawPublic));

此处secp256r1的公钥的长度始终为64字节。私钥的大小为32字节,但也可以更小。


dave_thompson_085在他的评论(java.security.interfaces(中指出了ECPublicKeyECPrivateKey的内置Java实现。这里,私钥和公钥的对应方法分别是getS()getW()
在x或y小于32字节的情况下,此实现不会自动填充前导0x00值,因此必须手动执行。因此,BouncyCastle方法可能对您更方便,这也是因为您已经使用了BouncyCCastle。

最新更新