簡體   English   中英

無法在 Golang 中從 iOS 解析 base64 DER 編碼的 ASN.1 公鑰

[英]Could not parse base64 DER-encoded ASN.1 public key from iOS in Golang

我在 Golang 中有一個帶有 RSA enryption 的項目,所以現在,我有一個 Base64 公鑰格式,用於加密消息,

我使用了這個代碼:

publicKeyBase64 = "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)

publicKeyInterface, err := x509.ParsePKIXPublicKey(publicKeyBinary)
    if err != nil {
    fmt.Println("Could not parse DER encoded public key (encryption key)")
    return "","",err
}

publicKey, isRSAPublicKey := publicKeyInterface.(*rsa.PublicKey)
if !isRSAPublicKey {
    fmt.Println("Public key parsed is not an RSA public key")
    return "","",err
}

encryptedMessage, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, "message")

當我運行此代碼時,出現此錯誤:

Could not parse DER encoded public key (encryption key)

asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier @3

錯誤指向 publicKeyInterface,它無法從 Base64 解碼格式解析為公鑰,我的代碼有什么問題?

======更新=====

我的 publicKeyBase64 是從二進制數據類型的模型中檢索的

當我從 Rails API 將它存儲在我的 mongoDB 中時,我以 Base64 格式接收 public_key 參數,但我將它解碼為二進制文件,然后我用此代碼存儲它

def create
  params = device_params      
  public_key = Base64.decode64 device_params[:public_key]
  #device_params[:public_key] value is "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
  params[:public_key] = BSON::Binary.new(public_key, :generic)
  device = Device.find_or_create_by(id: device_params[:id])

  render_success device.update_attributes(params), device
end

當我使用 rails 代碼使用此代碼轉換我的 Base64 公鑰字符串時,它成功了:

rsa_public_key = OpenSSL::PKey::RSA.new(Base64.decode64(public_key))

在我的 iOS 應用程序中,我使用https://github.com/DigitalLeaves/AsymmetricCrypto使用以下代碼生成公鑰:

AsymmetricCryptoManager.sharedInstance.createSecureKeyPair({ (success, error) -> Void in
   if success {
    print("RSA-1024 keypair successfully generated.")
    let publicKey = AsymmetricCryptoManager.sharedInstance.getPublicKeyData()?.base64EncodedString()

    let url = ENV.BASE_URL + "devices"
    let headers = ["Authentication-Token": CurrentUser.getCurrentUser().token] as! HTTPHeaders
    let params = ["device[user_id]": CurrentUser.getCurrentUser().id!, "device[id]": instanceID,"device[token]": fcmToken, "device[os]": "ios", "device[public_key]": publicKey!]

    Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default, headers: headers)
} else { print("An error happened while generating a keypair: \(error)") }
})

我們可以轉儲 ASN.1 內容以查看它們的外觀:

$ echo "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE=" | \
    base64 -d | \
    dumpasn1 -
  0 137: SEQUENCE {
  3 129:   INTEGER
       :     00 92 58 5E 00 5E 9B 5B 1C 2C A3 C4 8F 02 AB 5B
       :     CF 9C 8B 70 7F 60 D3 77 69 8D 83 27 79 5C E5 ED
       :     B0 35 CD 12 98 58 A4 0E 9A 30 D5 37 58 70 A9 76
       :     C1 DA D7 5F BB 0C 46 CC A3 4E 4D 79 20 40 8C 7B
       :     3C 87 CD A2 46 43 D4 E2 9E 79 10 8B 12 7E 62 79
       :     4D 74 B0 B4 E1 33 56 3A 0D 77 A6 5C 9A 84 85 C1
       :     7E 8A D8 02 36 25 DB 05 48 03 C6 26 6B 66 C4 40
       :     58 66 00 59 04 5F 50 3F 43 57 48 2B 2E 84 7D 0F
       :     B1
135   3:   INTEGER 65537
       :   }

0 warnings, 0 errors.

格式良好的 ASN.1 公鑰也應包含該算法。 我們應該有一行類似於:

  5   9:     OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)

AsymmetricCryptoManager.getPublicKeyData()返回一個非常准的ASN.1密鑰,沒有任何算法信息。 這讓 Go 很不高興,因為它無法知道它是什么類型的鍵。 在此處查看有關正確導出密鑰的更多信息

如果您可以更改 iOS 代碼,則應改為使用CryptoExportImportManager並使用exportPublicKeyToPEMexportPublicKeyToDER 這些獲取getPublicKeyData的輸出並生成其他工具可用的輸出。 您可以在CryptoExportImportManager 示例中找到有關如何使用它們的示例

如果您無法更改密鑰導出代碼,則可以直接在 Go 中對其進行解析。 這假設您確定它是 RSA 公鑰:

func main() {
    publicKeyBase64 := "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="

    // Base64 decode.
    publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)
    if err != nil {
        panic(err)
    }

    // rsa.PublicKey is a big.Int (N: modulus) and an integer (E: exponent).
    var pubKey rsa.PublicKey
    if rest, err := asn1.Unmarshal(publicKeyBinary, &pubKey); err != nil {
        panic(err)
    } else if len(rest) != 0 {
        panic("rest is not nil")
    }

    fmt.Printf("key: %+v\n", pubKey)
}

這打印出來:

項:{N:+102767083290202280873554060983826675083148443795791447833515664566475334389364583758312108980110921996262487865832851258326049062353432991986398760705560379825908169063986770245967781444794847106351934016144540466696422397564949226710181429429140226472206572796987719088983654589217713611861345869296293449649 E:65537}

您現在可以在包 rsa 函數中使用您的公鑰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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