使用BouncyCastle从文件中读取椭圆曲线私钥
BouncyCastle加密API允许使用常规java.security
包对象创建和validation数字签名,例如java.security.PublicKey
, java.security.PrivateKey
及其容器java.security.KeyPair
。
假设我使用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-----
如何使用BouncyCastle API获取包含此私钥和相应公钥的java.security.KeyPair
?
请注意我想使用BouncyCastle 1.50中提供的API(在撰写本文时是最新的)并且没有弃用的API。 遗憾的是,这不包括其他SO答案中使用的PEMReader
类。 此外,这个问题特定于椭圆曲线的格式; 在比较RSA或DSA密钥文件时,它们包含其他参数。
在Java中,这将是几乎相同的代码。 剥离保护字符串并解码Base64数据后,将其提供给此实用程序方法:
public static PrivateKey keyToValue(byte[] pkcs8key) throw GeneralSecurityException { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pkcs8key); KeyFactory factory = KeyFactory.getInstance("ECDSA"); PrivateKey privateKey = factory.generatePrivate(spec); return privateKey; }
除了divanov显示的标准JCE方法,只要你给它正确的输入(参见我的评论),或者只是像你的selfanswer一样使用JCE, BouncyCastle 1.48 up DOES仍然包含刚刚组织的旧PEMReaderfunction有点不同,在这种情况下你可以使用类似的东西:
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()); }
由于我只需要这个快速而肮脏的演示,我通过以下方式解决了它(在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)
然后使用生成的数据,
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)
您需要知道的关键是默认情况下公钥数据使用X509编码,私钥数据使用PKCS8编码。 应该可以让OpenSSL输出这些格式并手动解析它们,但我没有检查如何。
我使用这个博客文章中有关SpongyCastle(这是Android的BouncyCastle别名)的信息非常有帮助。 遗憾的是,文档像这样碎片化,并且BouncyCastle的wiki在这个问题时已经失效了。
更新 :BouncyCastle wiki已启动,您可以在此处找到文档。
- 使用轻量级API生成Bouncy Castle RSA密钥对
- 我可以使用标准Java Cipher API使用BouncyCastle的Tweakable Block Ciphers吗?
- ECDSA算法教程对字符串进行签名
- SHA256withRSA和SHA256之间的区别然后是RSA
- Java BouncyCastle ECC密钥和自签名证书
- 如何使用新的Bouncy Castle库从PKCS10CertificationRequest获取PublicKey?
- 使用BouncyCastle将签名/身份validation的属性添加到CMS签名
- 如何从pem文件加载公共证书?
- 如何使用PDFBox对动态创建的PDF文档进行数字签名?