簡體   English   中英

如何解析(進入模數和指數)特定的 ASN1 RSA 公鑰以便構建 RSAPublicKeySpec? Android Java/Kotlin 案例

[英]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 解析器。 所需的類是PemReaderASN1Sequence
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM