如何从私钥字节创建PrivateKey对象?



假设我有一个种子:this is a seed that i might have lying around somewhere
然后我对种子进行哈希以产生大小为32的字节数组
根据我的理解(从本文中),这现在是我的私钥字节。如何将这些字节转换为PrivateKey对象?

据我所见,大概是这样的:

KeyFactory kf = KeyFactory.getInstance("EC");
PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));

但要使其工作,私钥字节应该采用pkcs# 8格式。由于我是通过散列种子生成私钥字节的,因此它们显然不是。

所以我的问题是:我如何将我的私钥字节编码为pkcs# 8,或者,除了PKCS8EncodedKeySpec之外,是否还有另一个类可以这样做?

我正在使用ECDSA

我使用secp256k1

…我是否将我的私钥字节编码为pkcs# 8,或者,除了PKCS8EncodedKeySpec之外,还有其他类可以做到这一点?

Yes and Yes .

选项A:构造一个像PKCS8这样的DER编码通常是复杂的,但对于PKCS8的特定情况,未加密的包含"命名"(OID)形式的EC密钥,这是每个人(特别是Java加密)现在使用的,更简单,并且给定曲线由固定前缀后跟私钥字节组成。看看我对这个问题的回答,主要是关于从私钥计算公钥,但是我的例子在回答其他问题的过程中使用pkcs8化的私钥。

注意,在java 9升级版(在这个答案之后发布)中,默认情况下,java.xml.bind.DatatypeConverter在java ase中不再可用,因此您要么需要将其作为依赖项,要么替换为功能等效的东西——关于这个问题有很多问题。

选项B:代替使用PKSC8(编码)表示,您可以使用ECPrivateKeySpec。

标准(Oracle/Open) Java不提供单独获取参数的简单方法,因此我发现最好的方法是生成一个虚拟密钥并丢弃它:
/* workaround is unnecessary
KeyPairGenerator kg = KeyPairGenerator.getInstance("EC");
kg.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec param = ((ECPublicKey)kg.generateKeyPair().getPublic()).getParams();
--- instead do: */
AlgorithmParameters a = AlgorithmParameters.getInstance("EC");
a.init(new ECGenParameterSpec("secp256k1"));
ECParameterSpec p = a.getParameterSpec(ECParameterSpec.class);
BigInteger s = new BigInteger(1, /*byte[32] privatekey value*/);
KeyFactory kf = KeyFactory.getInstance("EC");
PrivateKey kp = kf.generatePrivate(new ECPrivateKeySpec(s, param));
// castable to ECPrivateKey if desired/needed

如果你使用BouncyCastle的直接(非jca) API,它会按名称提供EC参数;如果你需要的话,我可以给你找一些仿冒品。

警告:如果"躺在某处"不是使用足够的熵正确实现的随机过程的输出,特别是"种子"是由人类选择或记住的,这样做是不安全的。如果你把它用在比特币上——你没有说,但这是大多数无知、未经训练的人的用例,他们突然想做ECC,因为他们认为这会让他们变得更聪明、更富有、更性感、更出名——你可能会损失你的钱;参见https://en.bitcoin.it/wiki/Brainwallet。但这与StackOverflow无关。

最新更新