亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用來自 Java 的公鑰實現進行 RSA 解密

使用來自 Java 的公鑰實現進行 RSA 解密

Go
絕地無雙 2022-09-26 19:32:46
提供程序具有此示例 JAVA 代碼,用于使用公鑰解密 RSA。 public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)            throws Exception {        byte[] keyBytes = Base64.decodeBase64(publicKey);        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);        KeyFactory keyFactory = KeyFactory.getInstance("RSA");        Key publicK = keyFactory.generatePublic(x509KeySpec);        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());                cipher.init(Cipher.DECRYPT_MODE, publicK);        int inputLen = encryptedData.length;        ByteArrayOutputStream out = new ByteArrayOutputStream();        int offSet = 0;        byte[] cache;        int i = 0;        while (inputLen - offSet > 0) {            if (inputLen - offSet >(2048/8)) {                cache = cipher.doFinal(encryptedData, offSet,(2048/8));            } else {                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);            }            out.write(cache, 0, cache.length);            i++;            offSet = i *(2048/8);        }        byte[] decryptedData = out.toByteArray();        out.close();        return decryptedData;    }我試圖在Go中寫下等價物,但沒有任何運氣。base64DecodeBytesKey, err := base64.StdEncoding.DecodeString(os.Getenv("PUBKEY"))    if err != nil {        Log(logRef, " error reading  pubkey", err)    }    pubKey, err := x509.ParsePKCS1PrivateKey(base64DecodeBytesKey)c := new(big.Int)    m := new(big.Int)    m.SetBytes(data)    e := big.NewInt(int64(pubKey.E))    c.Exp(m, e, pubKey.N)    out := c.Bytes()    skip := 0以上是第一次嘗試,但失敗了。 確實需要私鑰,提供商堅持認為這不是必需的。rsa.DecryptPKCS1v15encryptedBlockBytes, err := rsa.DecryptPKCS1v15(            rand.Reader,            NO_PRIVATE_KEY_PROVIDED,            payloadBytes[start:finish])    有沒有辦法使用Go加密庫從RSA驗證PSS中獲取解密的有效負載?
查看完整描述

1 回答

?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

從Java代碼中,填充并不明確,因為只指定了算法,而沒有指定填充。在這種情況下,填充取決于提供者,例如 SunJCE 提供者的 PKCS#1 v1.5。

假設 PKCS#1 v1.5,則 /私鑰和 /公鑰的組合將 RSASSA-PKCS1-v1_5作為填充。這在功能上與簽名/驗證相同(除了使用 NonewithRSA 進行驗證還會與使用公鑰解密相比檢查數據的相等性)。Cipher.ENCRYPT_MODECipher.DECRYPT_MODENonewithRSA

無與RSA意味著數據不進行哈希處理,并且沒有預置摘要ID。此算法實際上旨在對已散列的數據進行簽名(在預置摘要 ID 之后)。它絕不是要對未哈希的數據進行簽名,即Java代碼濫用此算法。
由于消息大小受 RSA 限制(密鑰大小減去填充所需的空間),因此只能對適當的短消息進行簽名。因此,大小超過允許大小的未哈希數據將強制使用多個簽名。這就是 Java 代碼中多次解密的原因。
使用散列數據不僅出于實際原因(簽署長消息)而有用,而且出于安全原因也是必要的,例如這里這里

要在 Go 中實現 Java 代碼的功能,需要一個低級實現,以便在 Go 中簽名/驗證,就像在 Java 代碼中一樣。
另一種可能性是實現解密(m = c^e)并自己刪除填充,對于RSASSA-PKCS1-v1_5,它只是由一系列0xFF值組成,這些值由左側的0x0001和右側的0x00構成。

在下文中,我將考慮第二種方法。下面的 Go 代碼執行以下操作:

  • 導入公鑰

  • Base64 解碼密文

  • 將密文拆分為單獨的簽名塊(此處為包含相同數據的3個塊:快速的棕色狐貍跳過懶惰的狗)

  • 解密每個簽名塊 (m = c ^ e)

  • 連接解密的簽名區塊

package main


import (

    "fmt"

    "math/big"

    "encoding/pem"

    "crypto/x509"

    "crypto/rsa"

    "encoding/base64"

    "bytes"

    "io"

)


func main() {


    pubKeyPem := `-----BEGIN PUBLIC KEY-----

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFB

mwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKH

yVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+I

d0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DI

hFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U

1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RC

sQIDAQAB

-----END PUBLIC KEY-----`


    // Import public key

    pubKey := ImportSPKIPublicKeyPEM(pubKeyPem);    

    // Base64 decode ciphertext

    ciphertextBytes, _ := base64.StdEncoding.DecodeString("ajQbkszbZ97YZaPSRBab9vj0DDLm9tTrQwSZ+ucPj+cYSmw06KLCtRH3SPn3b2DqSd1revLXqxMtSzFmjRvZ5F8y3nzdP8NJaRplOigbPFhKZTv7xBVK5ATEmLukgtI7f+d3KdmGUG+cyTkfxIrMBvB3BIS5oTiMNmC9pqLaWcDVF9qpuxnwEMQJbeO9nTklpdv+F8BrchHmeUkKRrMJBoPbbcfq9Hi4bHiFyxPWhwB66d/AryCKsFRhaX6hSkTL+0NvuhVhv98wdo3juv2Il50XKOCbfc8kUG628TcSK6n31piLF9cntSVTB/L/pVfcAxEwx4hcUhLuqmk6EZIJvGo0G5LM22fe2GWj0kQWm/b49Awy5vbU60MEmfrnD4/nGEpsNOiiwrUR90j5929g6knda3ry16sTLUsxZo0b2eRfMt583T/DSWkaZTooGzxYSmU7+8QVSuQExJi7pILSO3/ndynZhlBvnMk5H8SKzAbwdwSEuaE4jDZgvaai2lnA1RfaqbsZ8BDECW3jvZ05JaXb/hfAa3IR5nlJCkazCQaD223H6vR4uGx4hcsT1ocAeunfwK8girBUYWl+oUpEy/tDb7oVYb/fMHaN47r9iJedFyjgm33PJFButvE3Eiup99aYixfXJ7UlUwfy/6VX3AMRMMeIXFIS7qppOhGSCbxqNBuSzNtn3thlo9JEFpv2+PQMMub21OtDBJn65w+P5xhKbDToosK1EfdI+fdvYOpJ3Wt68terEy1LMWaNG9nkXzLefN0/w0lpGmU6KBs8WEplO/vEFUrkBMSYu6SC0jt/53cp2YZQb5zJOR/EiswG8HcEhLmhOIw2YL2motpZwNUX2qm7GfAQxAlt472dOSWl2/4XwGtyEeZ5SQpGswkGg9ttx+r0eLhseIXLE9aHAHrp38CvIIqwVGFpfqFKRMv7Q2+6FWG/3zB2jeO6/YiXnRco4Jt9zyRQbrbxNxIrqffWmIsX1ye1JVMH8v+lV9wDETDHiFxSEu6qaToRkgm8")

    // Split ciphertext into signature chunks a 2048/8 bytes and decrypt each chunk

    reader := bytes.NewReader(ciphertextBytes)

    var writer bytes.Buffer

    ciphertextBytesChunk := make([]byte, 2048/8)

    for { 

        n, _ := io.ReadFull(reader, ciphertextBytesChunk)

        if (n == 0) { 

            break

        }

        decryptChunk(ciphertextBytesChunk, &writer, pubKey)

    }

    // Concatenate decrypted signature chunks

    decryptedData := writer.String()

    fmt.Println(decryptedData)      

}


func ImportSPKIPublicKeyPEM(spkiPEM string) (*rsa.PublicKey) {

    body, _ := pem.Decode([]byte(spkiPEM )) 

    publicKey, _ := x509.ParsePKIXPublicKey(body.Bytes)

    if publicKey, ok := publicKey.(*rsa.PublicKey); ok {

        return publicKey

    } else {

        return nil

    }   

}


func decryptChunk(ciphertextBytesChunk []byte , writer *bytes.Buffer, pubKey *rsa.PublicKey ){

    // Decrypt each signature chunk

    ciphertextInt := new(big.Int)

    ciphertextInt.SetBytes(ciphertextBytesChunk)

    decryptedPaddedInt := decrypt(new(big.Int), pubKey, ciphertextInt)  

    // Remove padding

    decryptedPaddedBytes := make([]byte, pubKey.Size())

    decryptedPaddedInt.FillBytes(decryptedPaddedBytes)

    start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00<data>: Find index after 2nd 0x00

    decryptedBytes := decryptedPaddedBytes[start:]  

    // Write decrypted signature chunk

    writer.Write(decryptedBytes)

}


func decrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int {

    // Textbook RSA

    e := big.NewInt(int64(pub.E))

    c.Exp(m, e, pub.N)

    return c

}

輸出:


The quick brown fox jumps over the lazy dogThe quick brown fox jumps over the lazy dogThe quick brown fox jumps over the lazy dog

請注意,代碼只是一個示例實現,特別是不包括異常處理。


測試:

下面的 Java 代碼


String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFBmwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKHyVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+Id0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DIhFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RCsQIDAQAB"; 

byte[] ciphertext = Base64.getDecoder().decode("ajQbkszbZ97YZaPSRBab9vj0DDLm9tTrQwSZ+ucPj+cYSmw06KLCtRH3SPn3b2DqSd1revLXqxMtSzFmjRvZ5F8y3nzdP8NJaRplOigbPFhKZTv7xBVK5ATEmLukgtI7f+d3KdmGUG+cyTkfxIrMBvB3BIS5oTiMNmC9pqLaWcDVF9qpuxnwEMQJbeO9nTklpdv+F8BrchHmeUkKRrMJBoPbbcfq9Hi4bHiFyxPWhwB66d/AryCKsFRhaX6hSkTL+0NvuhVhv98wdo3juv2Il50XKOCbfc8kUG628TcSK6n31piLF9cntSVTB/L/pVfcAxEwx4hcUhLuqmk6EZIJvGo0G5LM22fe2GWj0kQWm/b49Awy5vbU60MEmfrnD4/nGEpsNOiiwrUR90j5929g6knda3ry16sTLUsxZo0b2eRfMt583T/DSWkaZTooGzxYSmU7+8QVSuQExJi7pILSO3/ndynZhlBvnMk5H8SKzAbwdwSEuaE4jDZgvaai2lnA1RfaqbsZ8BDECW3jvZ05JaXb/hfAa3IR5nlJCkazCQaD223H6vR4uGx4hcsT1ocAeunfwK8girBUYWl+oUpEy/tDb7oVYb/fMHaN47r9iJedFyjgm33PJFButvE3Eiup99aYixfXJ7UlUwfy/6VX3AMRMMeIXFIS7qppOhGSCbxqNBuSzNtn3thlo9JEFpv2+PQMMub21OtDBJn65w+P5xhKbDToosK1EfdI+fdvYOpJ3Wt68terEy1LMWaNG9nkXzLefN0/w0lpGmU6KBs8WEplO/vEFUrkBMSYu6SC0jt/53cp2YZQb5zJOR/EiswG8HcEhLmhOIw2YL2motpZwNUX2qm7GfAQxAlt472dOSWl2/4XwGtyEeZ5SQpGswkGg9ttx+r0eLhseIXLE9aHAHrp38CvIIqwVGFpfqFKRMv7Q2+6FWG/3zB2jeO6/YiXnRco4Jt9zyRQbrbxNxIrqffWmIsX1ye1JVMH8v+lV9wDETDHiFxSEu6qaToRkgm8");

byte[] decrypted = decryptByPublicKey(ciphertext, publicKey); 

System.out.println(new String(decrypted, StandardCharsets.UTF_8));

使用您發布的方法給出相同的結果。


查看完整回答
反對 回復 2022-09-26
  • 1 回答
  • 0 關注
  • 211 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號