Java 使用 BouncyCastle 从文件中读取椭圆曲线私钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22963581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading elliptic curve private key from file with BouncyCastle
提问by DCKing
The BouncyCastle cryptography APIs allow for creating and verifying digital signatures using the regular java.security
package objects, such as java.security.PublicKey
, java.security.PrivateKey
and their container java.security.KeyPair
.
该BouncyCastle的加密API允许创建和使用的常规验证数字签名java.security
包对象,如java.security.PublicKey
,java.security.PrivateKey
和它们的容器java.security.KeyPair
。
Suppose I use OpenSSL to create a .pem (or, if easier, a .der file) containing the elliptic curve private key I want to use in my application. For example, it looks like this:
假设我使用 OpenSSL 创建一个 .pem(或者,如果更简单,一个 .der 文件),其中包含我想在我的应用程序中使用的椭圆曲线私钥。例如,它看起来像这样:
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIDzESrZFmTaOozu2NyiS8LMZGqkHfpSOoI/qA9Lw+d4NoAcGBSuBBAAK
oUQDQgAE7kIqoSQzC/UUXdFdQ9Xvu1Lri7pFfd7xDbQWhSqHaDtj+XY36Z1Cznun
GDxlA0AavdVDuoGXxNQPIed3FxPE3Q==
-----END EC PRIVATE KEY-----
How do I use the BouncyCastle APIs to obtain a java.security.KeyPair
containing both this private key and a corresponding public key?
如何使用 BouncyCastle API 获取java.security.KeyPair
包含此私钥和相应公钥的密钥?
Please note I want to use the APIs available in BouncyCastle 1.50 (which is current at the time of writing) and no deprecated APIs. This unfortunately excludes the PEMReader
class used in other SO answers. Furthermore, this question is specific to the format of elliptic curves; they contain additional parameters when compared RSA or DSA key files.
请注意,我想使用 BouncyCastle 1.50(在撰写本文时为最新版本)中可用的 API,并且没有弃用的 API。不幸的是,这排除了PEMReader
其他 SO 答案中使用的类。此外,这个问题特定于椭圆曲线的格式;当比较 RSA 或 DSA 密钥文件时,它们包含附加参数。
采纳答案by divanov
In Java this will be pretty much the same code. After striping guarding strings away and decoding Base64 data give it to this utility method:
在 Java 中,这将是几乎相同的代码。在剥离保护字符串并解码 Base64 数据后,将其提供给此实用程序方法:
public static PrivateKey keyToValue(byte[] pkcs8key)
throws GeneralSecurityException {
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkcs8key);
KeyFactory factory = KeyFactory.getInstance("ECDSA");
PrivateKey privateKey = factory.generatePrivate(spec);
return privateKey;
}
回答by DCKing
Since I only need this for a quick and dirty demo, I solved it in the following way (in Scala). First, I generate a public private key pair in the REPL and print out its data:
由于我只需要它来进行快速而肮脏的演示,因此我通过以下方式(在 Scala 中)解决了它。首先,我在 REPL 中生成一个公私钥对并打印出它的数据:
Security.addProvider(new BouncyCastleProvider)
val SignatureScheme = "some signature scheme, eg ECDSA"
val RandomAlgorithm = "some random algorithm, eg SHA1PRNG"
val keygen = KeyPairGenerator.getInstance(SignatureScheme)
val rng = SecureRandom.getInstance(RandomAlgorithm)
rng.setSeed(seed)
keygen.initialize(KeySize, rng)
val kp = keygen.generateKeyPair()
println(kp.getPublic.getEncoded.toSeq) // toSeq so that Scala actually prints it
println(kp.getPrivate.getEncoded.toSeq)
Then using the generated data,
然后使用生成的数据,
val hardcodedPublic = Array[Byte]( /* data */ )
val hardcodedPrivate = Array[Byte]( /* data */ )
val factory = KeyFactory.getInstance(SignatureScheme)
val publicSpec = new X509EncodedKeySpec(hardcodedPublic)
val publicKey = factory.generatePublic(publicSpec)
val privateSpec = new PKCS8EncodedKeySpec(hardcodedPrivate)
val privateKey = factory.generatePrivate(privateSpec)
The key thing you need to know here is that by default public key data uses X509 encoding and private key data uses PKCS8 encoding. It should be possible to get OpenSSL to output these formats and parse them manually, but I did not check how.
这里您需要知道的关键是,默认情况下,公钥数据使用 X509 编码,私钥数据使用 PKCS8 编码。应该可以让 OpenSSL 输出这些格式并手动解析它们,但我没有检查如何。
I used information from this blog postabout SpongyCastle (which is Android's BouncyCastle alias) quite helpful. It is unfortunate that documentation is fragmented like this, and that BouncyCastle's wiki was down at the time of this question.
我使用了这篇博文中关于 SpongyCastle(这是 Android 的 BouncyCastle 别名)的信息非常有帮助。不幸的是,文档像这样支离破碎,并且 BouncyCastle 的 wiki 在提出这个问题时已关闭。
Update: the BouncyCastle wiki is up, and you can find the documentation here.
更新:BouncyCastle wiki 已上线,您可以在此处找到文档。
回答by dave_thompson_085
In addition to the standard JCE approach shown by divanovas long as you give it the correct input (see my comment thereto), or just using JCE in the first place like your selfanswer, BouncyCastle1.48 up DOES still contain the old PEMReader functionality just organized a bit differently and for this case you can usesomething like:
除了divanov 显示的标准 JCE 方法,只要你给它正确的输入(见我的评论),或者像你的 selfanswer 一样首先使用 JCE,BouncyCastle1.48 up DOES 仍然包含刚刚组织的旧 PEMReader 功能有点不同,对于这种情况,您可以使用以下内容:
static void SO22963581BCPEMPrivateEC () throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Reader rdr = new StringReader ("-----BEGIN EC PRIVATE KEY-----\n"
+"MHQCAQEEIDzESrZFmTaOozu2NyiS8LMZGqkHfpSOoI/qA9Lw+d4NoAcGBSuBBAAK\n"
+"oUQDQgAE7kIqoSQzC/UUXdFdQ9Xvu1Lri7pFfd7xDbQWhSqHaDtj+XY36Z1Cznun\n"
+"GDxlA0AavdVDuoGXxNQPIed3FxPE3Q==\n"+"-----END EC PRIVATE KEY-----\n");
Object parsed = new org.bouncycastle.openssl.PEMParser(rdr).readObject();
KeyPair pair = new org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter().getKeyPair((org.bouncycastle.openssl.PEMKeyPair)parsed);
System.out.println (pair.getPrivate().getAlgorithm());
}