提问人:user2517182 提问时间:11/8/2023 最后编辑:user2517182 更新时间:11/8/2023 访问量:60
如何使用 kotlin 从 RSA 私钥获取 ECDSA、DER 和 RPB 格式
How to get the ECDSA, DER and RPB format from a RSA private key using kotlin
问:
我有一个 RSA 私钥。我想以下列格式提取公钥:
- ECDSA的
- DER
- RPB公司
我可以使用以下代码从 RSA 格式的私钥获取 RSA 格式的公共密钥。
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.PublicKey
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.RSAPrivateCrtKeySpec
import java.security.interfaces.RSAPrivateCrtKey
import java.security.spec.RSAPublicKeySpec
import java.util.Base64
import java.security.KeyPair
import java.security.KeyPairGenerator
const val ALGORITHM = "RSA"
fun generateKeyPair(): KeyPair {
val keyPairGenerator = KeyPairGenerator.getInstance("RSA")
keyPairGenerator.initialize(2048) // You can adjust the key size as needed
return keyPairGenerator.generateKeyPair()
}
fun generatePublicKey(privateKeyString: String): PublicKey {
try {
val kf = KeyFactory.getInstance(ALGORITHM)
val encodedPrivateKey = Base64.getDecoder().decode(privateKeyString)
val privateKeySpec = PKCS8EncodedKeySpec(encodedPrivateKey)
val rsaPrivateKey = kf.generatePrivate(privateKeySpec) as RSAPrivateCrtKey
val publicKeySpec = RSAPublicKeySpec(rsaPrivateKey.modulus, rsaPrivateKey.publicExponent)
return kf.generatePublic(publicKeySpec)
} catch (e: Exception) {
throw RuntimeException(e)
}
}
fun main() {
val keyPair = generateKeyPair()
// val publicKey: PublicKey = keyPair.public
val privateKey: PrivateKey = keyPair.private
// Test with a sample private key string
val privateKeyString = Base64.getEncoder().encodeToString(privateKey.encoded)
println("Generated Private Key: $privateKeyString")
//val privateKeyString = "YOUR_PRIVATE_KEY_STRING_HERE"
val publicKey = generatePublicKey(privateKeyString)
println("Generated Public Key: ${Base64.getEncoder().encodeToString(publicKey.encoded)}")
}
既然有,我以为会有一个 、 和 。但是,我错了。不过,还有其他格式类型。java.security.spec
RSAPublicKeySpec
ECDSAPublicKeySpec
DERPublicKeySpec
RPBPublicKeySpec
PublicKeySpec
我看了一下充气城堡,但无法从私钥(或从 RSA 格式转换为三种格式)获取三种格式。
我知道 OpenSSL 在带有一些标志的三个命令中完成了我所要求的一切。我不能使用 OpenSSL,我需要在没有 OpenSSL 包装器的情况下用 kotlin 进行。
我相信有 Java Cryptography Extension (JCE) 和 Bouncy Castle(可能会再次检查)扩展了 Java 中加密的一些功能。但是,在我访问/重新访问之前,我将来到我值得信赖的 Stackoverflow 社区。
更新:
以下是我尝试通过 Kotlin(和 Java 库)重新创建的 OpenSSL 中的命令。特别强调代码中具有 --> NEED THIS <-- 的注释
// Private key --> already have this
openssl genrsa -out priv.pem 2048
// Public key --> already have this
openssl rsa -in priv.pem -pubout -out pub.pem
// Public key PEM --> already have this
openssl pkey -inform PEM -pubin -in pub.pem -text -noout
// Public key DER format --> NEED THIS <--
openssl rsa -pubin -inform PEM -in pub.pem -outform DER -out pub.der
// Public key RPB format --> no worries about this
openssl rsa -pubin -inform PEM -in pub.pem -outform RPB -out pub.rpb
// ECDSA
// Private key --> already have this
openssl ecparam -genkey -out ecdsa_priv.pem -name prime256v1
// Public key --> NEED THIS <--
openssl ec -in ecdsa_priv.pem -pubout -out ecdsa_pub.pem
// Public key DER format --> NEED THIS <--
openssl ec -pubin -inform PEM -in ecdsa_pub.pem -outform DER -out ecdsa_pub.der
答:
公钥 PEM -->已经有这个
openssl pkey -inform PEM -pubin -in pub.pem -text -noout
没有。Java - 或者只是在 Kotlin 中 - 是 X.509-SPKI 格式的公钥,它与使用的格式相同。当你编码为 base64 并每隔 64 添加换行符并在之前和之后添加一行时,则它与 OpenSSL PEM 相同,这也是标准的;见第 2 节和第 13 节RFC7468。根据您将如何使用此文件或数据,您可能会在没有 base64 中的换行符的情况下逃脱;并非所有程序都需要这样做。但大多数使用 PEM 的程序都会强制执行 dash-BEGIN 和 dash-END 线。PublicKey.getEncoded()
.encoded
openssl
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
公钥 DER 格式 --> 需要这个<--
openssl rsa -pubin -inform PEM -in pub.pem -outform DER -out pub.der
这是微不足道的。只需跳过 base64 编码;返回的正是这种格式(作为)。PublicKey.getEncoded()
byte[]
公钥 RPB 格式 --> 不用担心这个
openssl rsa -pubin -inform PEM -in pub.pem -outform RPB -out pub.rpb
您正在使用的这个openssl是什么?你从哪里/怎么得到的?没有“真正的”OpenSSL(即来自 www.openssl.org 的 OpenSSL 项目)具有这样的选项。我也不认为 LibreSSL 会这样做,尽管我没有那么密切地跟踪它。-outform
ECDSA
// 私钥 --> 已经有这个 openssl ecparam -genkey -out ecdsa_priv.pem -name prime256v1 // 公钥 --> 需要这个<-- openssl ec -in ecdsa_priv.pem -pubout -out ecdsa_pub.pem /
/ 公钥 DER 格式 --> 需要这个
<--
openssl ec -pubin -inform PEM -in ecdsa_pub.pem
-outform DER -out ecdsa_pub.der
这些是从 EC 密钥(或真正的密钥对)生成的,而不是 RSA 密钥。请注意,尽管您使用了文件名 ecdsa,但实际上用于 ECDSA 和 ECDH 以及可能的 EQMQV 使用了相同的密钥;因此,在 Java 中,您使用 but 和 .KeyPairGenerator|KeyFactory.getInstance("EC")
Signature.getInstance("ECDSA")
KeyAgreement.getInstance("ECDH")
如果您有其中一个关键对象,即一个带有 interface not 的对象,以及您的帖子建议但实际上没有说明的 BouncyCastle,您可以调整我最近在 Extract public key 中写的方法 PrivateKeyInfo with Bouncy Castle:ECPrivateKey
RSAPrivateCrtKey
// import org.bouncycastle.asn1.pkcs.PrivateKeyInfo and org.bouncycastle.asn1.ASN1BitString
PrivateKeyInfo privinfo = PrivateKeyInfo.getInstance( ecprivkeyobject.getEncoded() );
ASN1BitString wrappt = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(privinfo.getPrivateKey().getOctets()).getPublicKey();
// use full name to avoid conflict with 'standard' java.security.interfaces.ECPrivateKey
byte[] spki = new SubjectPublicKeyInfo(privinfo.getPrivateKeyAlgorithm(), wrappt).getEncoded() ));
这是 EC 的 openssl DER 格式,类似于 RSA,如果您进行 base64 编码、添加换行符并添加 BEGIN/END 行,即 openssl(和标准 = RFC7468)PEM 格式。byte[] spki
补充:此外,您当前的 RSA 方法是不必要的迂回交叉路口。你不需要为RSA创建一个,采用它的编码,通过一个 with 运行该编码来产生你投射到的第二个;相反,您可以直接转换原始内容并使用它来获取 和 放入 .这个案例也在我链接的上一个Q中。PrivateKey
KeyFactory
PKCS8EncodedKeySpec
PrivateKey
RSAPrivateCrtKey
PrivateKey
modulus
publicExponent
RSAPublicKeySpec
评论