主頁 > 軟體設計 > 如何配置AndroidRSA密鑰生成(或密鑰使用),使其像DelphiTurboPowerLockbox2RSA密鑰生成/使用一樣作業?

如何配置AndroidRSA密鑰生成(或密鑰使用),使其像DelphiTurboPowerLockbox2RSA密鑰生成/使用一樣作業?

2022-10-11 09:16:27 軟體設計

我有以下代碼用于 Delphi 10.2 TurboPower LockBox 2 RSA 密鑰生成及其作為一些字串的表示:

//Object properties 
object LbRSA1024: TLbRSA
  PrimeTestIterations = 20
  KeySize = aks1024
  Left = 416
  Top = 248
end

//Key generation - so simple!
LbRSA1024.GenerateKeyPair;

//Getting generated key as string 
function TMainForm.GetPublicKey1024AsString: string;
var
  str1, str2: TStringStream;
begin
  Result:='';
  if (LbRSA1024.PublicKey.Exponent.Int.dwUsed = 0)
    or (LbRSA1024.PublicKey.Modulus.Int.dwUsed = 0) then
    exit;
  str1:= TStringStream.Create('');
  str2:= TStringStream.Create('');
  try
    LbRSA1024.PublicKey.StoreToStream(str1);
    str1.Position:=0;
    //LbEncodeBase64(str1,str2);
    TLbBase64.LbEncodeBase64(str1,str2);
    Result:=str2.DataString;
  finally
    str1.Free;
    str2.Free;
  end;
end;

我得到了大約 200 個字串的公鑰(例如 ...dh2dMTy/ab ...),我將他的字串分配給了 Android kotlin 變數 publicKeyString 并嘗試使用從 Delphi 生成的這個公鑰加密其他一些字串。Android Kotlin 代碼為:

    val publicKeyBytes: ByteArray = Base64.decode(publicKeyString, Base64.DEFAULT)
    val X509PublicKey: X509EncodedKeySpec = X509EncodedKeySpec(publicKeyBytes)
    val kf: KeyFactory = KeyFactory.getInstance("RSA")
    val publicKey: PublicKey = kf.generatePublic(X509PublicKey)
    val cipher: Cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")
    cipher.init(Cipher.ENCRYPT_MODE, publicKey)
    val bytes = cipher.doFinal(s.toByteArray())
    val result: String = String(bytes, Charsets.UTF_8)

通常它不起作用 - 密鑰不被接受并且錯誤訊息是(我嘗試了上面代碼的一些變體):

Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
 at sun.security.rsa.RSAKeyFactory.engineGeneratePublic (:-1)
...
Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
 at sun.security.rsa.RSAKeyFactory.engineGeneratePublic (:-1) 
 at java.security.KeyFactory.generatePublic (:-1) 

因此,Delphi LockBox 和 Android/javax RSA 可能具有不同的密鑰格式。所以 - 我試著做兩件事。首先 - 我檢查了 Delphi 密鑰生成的代碼 - 特別是 - LbRsa.pasclass procedure TRSA.GenerateRSAKeysEx(var PrivateKey, PublicKey : TLbRSAKey; KeySize : TLbAsymKeySize; PrimeTestIterations : Byte; Callback : TLbRSACallback);但是這個代碼是完全通用的 - 生成大整數并將其存盤為成員變數,然后使用我上面已經提供的代碼流式傳輸到字串。

然后我嘗試在 Android/javax 中生成 RSA 密鑰并檢查它們是否與 LockBox 生成的密鑰相同。我使用了以下代碼:

    val REG_KEY: String = "REG_KEY"
    val generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA /*, ANDROID_KEYSTORE */)
    val builder = KeyGenParameterSpec.Builder(REG_KEY,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
        .setKeySize(1024)
        .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
        //.setUserAuthenticationRequired(true)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
    generator.initialize(builder.build())
    val keys = generator.generateKeyPair()

    Log.i( "Cryptic", keys.private.toString())
    Log.i( "Cryptic", keys.public.toString())

    Log.i( "Cryptic", keys.private.encoded.contentToString())
    Log.i( "Cryptic", keys.public.encoded.contentToString())

    Log.i( "Cryptic", keys.private.encoded.toString(Charsets.UTF_8))
    Log.i( "Cryptic", keys.public.encoded.toString(Charsets.UTF_8))

我遇到錯誤訊息,因為私鑰為空,但生成了公鑰:

java.lang.NullPointerException: keys.private.encoded must not be null
        at com.batsoft.stockmobile.service.Cryptography.encryptString(Cryptography.kt:35)

我仍在尋求將其轉換為字串以看起來像 LockBox 生成的密鑰 - 只是為了比較。

但是現階段我已經很困惑了-為什么我必須為密鑰生成提供鏈接模式和填充方案?我的理解是密鑰只是編碼的大整數。并且鏈接模式,填充方案僅用于加密/解密?當然,我需要提供密鑰大小,這是可以理解的。

所以 - 我的目標是配置 Android/javax RSA 密鑰生成和 RSA 密鑰使用,使其完全符合 RSA 密鑰生成并在 Delphi 10.2 LockBox 2 中使用。我的目標是在 Android 程式中使用 LockBox 生成的密鑰。我已經描述了我已經采用的路徑數量,但我仍然沒有設法生成與 Delphi 密鑰格式相同的 javax 密鑰。因為我不知道他們在 LockBox 中的密鑰的確切配置(我猜 - 除了密鑰大小之外,沒有其他密鑰)我也無法在 Android/javax 上配置我的加密/解密。

如何通過更改 Android/javax 代碼來實作這種一致性?

附加資訊:Delphi LbAsym.pasprocedure TLbAsymmetricKey.StoreToStream(aStream : TStream);非常重要,因為它將鍵整數保存到流中。在不使用密碼短語的情況下,代碼非常緊張:

aStream.Write(KeyBuf, Len);

Pascal 代碼中的注釋如下:

save key to ASN.1 format stream (encrypt if necessary)

所以,也許我的問題需要重新表述——如何以 ASN.1 格式保存 Android/javax 生成的密鑰或從 ASN.1 格式讀取密鑰?

附加資訊 2:我正在尋找將 Java 生成的密鑰保存為 PEM 字串的方法,這可以通過 Android Kotlin 代碼完成:

    val generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA /*, ANDROID_KEYSTORE */)
    val builder = KeyGenParameterSpec.Builder(REG_KEY,
        KeyProperties.PURPOSE_ENCRYPT and KeyProperties.PURPOSE_DECRYPT)
        .setKeySize(1024)
        .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
        //.setUserAuthenticationRequired(true)
        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
    generator.initialize(builder.build())
    val keys = generator.generateKeyPair()

    //https://stackoverflow.com/questions/25129822/export-rsa-public-key-to-pem-string-using-java
    val writer = StringWriter()
    val pemWriter = PemWriter(writer)
    pemWriter.writeObject(PemObject("PUBLIC KEY", keys.public.encoded))
    pemWriter.flush()
    pemWriter.close()

    Log.i( "Cryptic", writer.toString())

注意,這需要添加 gradle 依賴項:

implementation 'org.bouncycastle:bcpkix-jdk15to18:1.68'
implementation 'org.bouncycastle:bcprov-jdk15to18:1.68'

為了使用 Delphi 生成的密鑰(顯然 LockBox 2 生成并將它們保存為 PEM 字串),我需要決議 PEM 字串并將它們分配為密鑰 javax Cipher。

附加資訊3:這很奇怪。Java 生成的字串(來自 Additional Info 2)是一個長約 25 個字符的 gan Delphi 生成的(基于 64 編碼的)字串(當然,我已經洗掉了一些帶有 PEM 檔案的初始和尾隨字串,它們只是像 '===PUBLIC KEY 這樣的常量===') 并且它可以在我的初始代碼中完美地用作 publicKeyString - 使用這種公鑰的加密作業完美。Delphi 公鑰字串短了大約 25 個字符并且不起作用。

所以 - 我已經弄清楚每個步驟中發生了什么并嘗試建立并行步驟,但最終我未能找到解決方案。

附加資訊 4:這里是 base64 編碼的公鑰:

從德爾福生成:

MIGIAoGBALtEMVXxHBWzBx/AzO/aOHrYEQZB3VlqYBvqX/SHES7ehERXaCbUO5aEwyZcDrdh2dMTy/abNDaFJK4bEqghpC6yvCNvnTqjAz bsD9UqS0w5CUh3KHwqhPv HFGcF7rAuU9uoJcWXbTC9tUBEG7rdmdmMatIgL1Y4ebOACQHn1xAgIlKg==

從 Android Kotlin/java 生成:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuQi7gMZwWL1iEhNVgdu23S/rYYhtntXQlfVVBjcGiSE8EXzjjnZHxcYHcIszV0F6F20msGK8MFernJpWg8k7J3GLH4TYkQwEEy6jWnRdEB3uqQWFCNQ/CflCHtq1o1iSS0qmXcHQuI7zZ0cHd5FNDg4Bl/DveftEje9yTgUXN3wIDAQAB

我不確定,但也許有一些在線服務可以對這些字串進行base64解碼,然后根據某種方案從中提取大整數并檢測格式。

uj5u.com熱心網友回復:

如評論中所述,Delphi 代碼生成 PKCS#1 格式的公鑰,而 Kotlin 代碼需要 X.509/SPKI 格式的密鑰。
使用 BouncyCastle,Kotlin 代碼可以匯入 PKCS#1 公鑰。這需要類PEMParserJcaPEMKeyConverter.

例子:

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.openssl.PEMParser
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
import javax.crypto.Cipher
import java.security.PublicKey
import java.io.FileReader
import java.util.Base64

...

val inputFile: String = "<path to PKCS#1 PEM file>"

// Key import
var publicKey: PublicKey? = null
FileReader(inputFile).use { fileReader ->
    PEMParser(fileReader).use { pemParser ->
        val spki: SubjectPublicKeyInfo = pemParser.readObject() as SubjectPublicKeyInfo
        val converter = JcaPEMKeyConverter()
        converter.setProvider(BouncyCastleProvider())
        publicKey = converter.getPublicKey(spki) 
    }
}

// Encryption
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 編碼的公鑰。PEM 編碼包括特定格式的頁眉和頁腳,并且在正文中,每 64 個字符后有換行符。PEM 編碼的 Delphi 密鑰是:

-----BEGIN RSA PUBLIC KEY-----
MIGIAoGBALtEMVXxHBWzBx/AzO/aOHrYEQZB3VlqYBvqX/SHES7ehERXaCbUO5aE
wyZcDrdh2dMTy/abNDaFJK4bEqghpC6yvCNvnTqjAz bsD9UqS0w5CUh3KHwqhPv
 HFGcF7rAuU9uoJcWXbTC9tUBEG7rdmdmMatIgL1Y4ebOACQHn1xAgIlKg==
-----END RSA PUBLIC KEY-----

不幸的是,您的 Delphi 密鑰的匯入不起作用。顯示了一個依賴于提供程式的錯誤訊息,例如在 BouncyCastleProvider 的情況下:

PEMException: unable to convert key pair: encoded key spec not recognized: RSA publicExponent is even

實際上,Delphi 代碼生成的密鑰有一個偶數公開指數,其值為 9514 (0x252A):

0:d=0  hl=3 l= 136 cons: SEQUENCE
    3:d=1  hl=3 l= 129 prim: INTEGER  :BB443155F11C15B3071FC0CCEFDA387AD8110641DD596A601BEA5FF487112EDE8444576826D43B9684C3265C0EB761D9D313CBF69B34368524AE1B12A821A42EB2BC236F9D3AA3033F9BB03F54A92D30E42521DCA1F0AA13EFF87146705EEB02E53DBA825C5976D30BDB540441BBADD99D98C6AD2202F563879B3800901E7D71
  135:d=1  hl=2 l=   2 prim: INTEGER  :252A

這不應該是這種情況(φ(n) 或 λ(n) 并且 e 將不是互質數),s。在這里因此,您應該檢查 Delphi 代碼中的密鑰生成。


另一個問題是:

val result: String = String(bytes, Charsets.UTF_8)

密文(通常包含不符合 UTF-8 的位元組序列)的 UTF-8 解碼會破壞該密文。
如果要將密文轉換為字串,則必須應用二進制到文本的編碼,例如 Base64。

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/513253.html

標籤:安卓德尔福RSAjavax.crypto密码箱-2

上一篇:例程可以知道它運行的單元嗎?

下一篇:軟邊緣圓形影像

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more