[英]Extract Modulus and Exponent from a RSA Public key in ASN.1 Format in Android
[英]How to parse (into modulus and exponent) specific ASN1 RSA public key so that one can build RSAPublicKeySpec? Android Java/Kotlin case
我有這個從 Delphi 10.2 TurboPower LockBox 2 模塊生成的公鑰:
MIGIAoGBALtEMVXxHBWzBx/AzO/aOHrYEQZB3VlqYBvqX/SHES7ehERXaCbUO5aEwyZcDrdh2dMTy/abNDaFJK4bEqghpC6yvCNvnTqjAz+bsD9UqS0w5CUh3KHwqhPv+HFGcF7rAuU9uoJcWXbTC9tUBEG7rdmdmMatIgL1Y4ebOACQHn1xAgIlKg==
這個 strang 可以被https://8gwifi.org/PemParserFunctions.jsp轉儲為:
Algo RSA
Format X.509
ASN1 Dump
RSA Public Key [60:df:88:a2:71:97:21:f2:45:88:94:6c:5a:63:1e:1e:8f:a0:50:a0]
modulus: bb443155f11c15b3071fc0ccefda387ad8110641dd596a601bea5ff487112ede8444576826d43b9684c3265c0eb761d9d313cbf69b34368524ae1b12a821a42eb2bc236f9d3aa3033f9bb03f54a92d30e42521dca1f0aa13eff87146705eeb02e53dba825c5976d30bdb540441bbadd99d98c6ad2202f563879b3800901e7d71
public exponent: 252a
並被https://lapo.it/asn1js轉儲為:
SEQUENCE (2 elem)
Offset: 0
Length: 3+136
(constructed)
Value:
(2 elem)
INTEGER (1024 bit) 131502922565366914567306533865977926602809520527330321378421375088553…
INTEGER 9514
因此,一些應用程序將其識別為有效的 RSA 公鑰 (1024)。 此字符串無法加載 Android Kotlin 代碼:
val publicKeyBytes: ByteArray = Base64.decode(publicKeyString, Base64.DEFAULT)
val X509PublicKey: X509EncodedKeySpec = X509EncodedKeySpec(publicKeyBytes)
//val RSAPublicKey: RSAPublicKeySpec = RSAPublicKeySpec()
val kf: KeyFactory = KeyFactory.getInstance("RSA")
val publicKey: PublicKey = kf.generatePublic(X509PublicKey)
錯誤代碼是:
java.security.spec.InvalidKeySpecException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: Error parsing public key
at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:305)
at com.android.org.conscrypt.OpenSSLRSAKeyFactory.engineGeneratePublic(OpenSSLRSAKeyFactory.java:55)
at java.security.KeyFactory.generatePublic(KeyFactory.java:361)
所以 - 我可以嘗試使用 RSAPublicKeySpec 而不是 X509EncodedKeySpec,但 RSAPublicKeySpec 期望 2 個 BigIntegers(指數和模數)作為構造函數 arguments。
我的問題是 - 如何將我的公鑰字符串(參見 exmaple 字符串及其解碼/轉儲 2 web 服務)解析為一對 BigIntegers 以用於 RSAPublicKeySpec?
要從 PKCS#1 密鑰中提取模數和公共指數,可以使用 BouncyCastle 的 ASN.1 解析器。 所需的類是PemReader
和ASN1Sequence
。
從ASN1Sequence
modulus 和 public exp.net 可以讀取。 然后兩者都可以用於創建RSAPublicKeySpec
。
例子:
import org.bouncycastle.asn1.ASN1Integer
import org.bouncycastle.asn1.ASN1Sequence
import org.bouncycastle.asn1.DLSequence
import org.bouncycastle.util.io.pem.PemReader
import java.io.FileReader
import java.security.KeyFactory
import java.security.PublicKey
import java.security.spec.RSAPublicKeySpec
import javax.crypto.Cipher
import java.util.Base64
...
val inputFile: String = "<path to PKCS#1 PEM file>"
// Key import
var publicKey: PublicKey? = null
FileReader(inputFile).use { fileReader ->
PemReader(fileReader).use { pemReader ->
val seq: DLSequence = ASN1Sequence.fromByteArray(pemReader.readPemObject().content) as DLSequence
val modulus: ASN1Integer = seq.elementAt(0) as ASN1Integer
val pubExp: ASN1Integer = seq.elementAt(1) as ASN1Integer
val publicKeySpec = RSAPublicKeySpec(modulus.positiveValue, pubExp.positiveValue)
val factory: KeyFactory = KeyFactory.getInstance("RSA")
publicKey = factory.generatePublic(publicKeySpec)
}
}
// Encrypt
val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
val ciphertext: ByteArray = cipher.doFinal("The quick brown fox jumps over the lazy dog".toByteArray())
val ciphertextB64: String = Base64.getEncoder().encodeToString(ciphertext);
println(ciphertextB64)
該代碼需要 PKCS#1 格式的 PEM 編碼公鑰。
正如這個答案中已經指出的那樣,密鑰不正確(公共指數是偶數)。 然而,提取所需信息的工作沒有錯誤消息。
但是,對於無效密鑰,結果通常不應被認為是可靠的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.