使用Java中的公钥实现进行RSA解密。

huangapple go评论83阅读模式
英文:

Go RSA decrypt using public key implementation from java

问题

以下是使用Go语言的等效代码:

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

func decryptByPublicKey(encryptedData []byte, publicKey string) ([]byte, error) {
	keyBytes, err := base64.StdEncoding.DecodeString(publicKey)
	if err != nil {
		return nil, err
	}

	pubKey, err := x509.ParsePKIXPublicKey(keyBytes)
	if err != nil {
		return nil, err
	}

	rsaPubKey, ok := pubKey.(*rsa.PublicKey)
	if !ok {
		return nil, fmt.Errorf("invalid public key type")
	}

	decryptedData, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, rsaPubKey, encryptedData, nil)
	if err != nil {
		return nil, err
	}

	return decryptedData, nil
}

你可以使用decryptByPublicKey函数来解密RSA加密的数据。它使用了Go语言的crypto/rsa包和crypto/sha256包来进行解密操作。请确保将encryptedDatapublicKey参数传递给函数,并处理返回的解密数据和错误。

英文:

Provider has this sample JAVA code to decrypt RSA using public key.

 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;
    }

I have tried to writ the equivalent in Go without any luck.

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
	Log(" payload size:--> ", len(data))
	for i := 2; i < len(out); i++ {
		if i+1 >= len(out) {
			break
		}
		if out[i] == 0xff && out[i+1] == 0 {
			skip = i + 2
			break
		}
	}
	return out[skip:]

Above was the first attempt which failed terribly.
rsa.DecryptPKCS1v15 does require a Private Key which the provider insists it's not necessary.

encryptedBlockBytes, err := rsa.DecryptPKCS1v15(
			rand.Reader,
			NO_PRIVATE_KEY_PROVIDED,
			payloadBytes[start:finish])
    

Is there a way to get the decrypted payload from RSA verify PSS using Go crypt library?

答案1

得分: 3

从Java代码中可以看出,填充方式并不清楚,因为只指定了算法,而没有指定填充方式。在这种情况下,填充方式取决于提供程序,例如SunJCE提供程序使用PKCS#1 v1.5填充。

假设使用PKCS#1 v1.5填充,组合Cipher.ENCRYPT_MODE/私钥和Cipher.DECRYPT_MODE/公钥将应用RSASSA-PKCS1-v1_5作为填充。这在功能上与使用NonewithRSA进行签名/验证是相同的(除了使用NonewithRSA进行验证还会检查数据与使用公钥进行解密的相等性)。

NonewithRSA表示数据未经哈希处理,且没有附加摘要ID。实际上,该算法旨在对已经进行哈希处理的数据进行签名(在附加摘要ID之后)。它绝不适用于对未经哈希处理的数据进行签名,即Java代码错误地使用了该算法。<br>
由于RSA的消息大小受限(密钥大小减去填充所需的空间),因此只能对适当长度的消息进行签名。超过允许大小的未经哈希处理的数据将强制进行多次签名。这就是Java代码中进行多次解密的原因。<br>
使用哈希处理的数据不仅有实际原因(签名长消息),而且出于安全原因也是必需的,参见这里这里

要在Go中实现Java代码的功能,需要像Java代码中一样在Go中进行低级别的签名/验证实现。<br>
另一种可能性是实现解密(m = c^e)并自行删除填充,对于RSASSA-PKCS1-v1_5,填充只是由0x0001左侧和0x00右侧的一系列0xFF值组成。

接下来,我考虑第二种方法。下面的Go代码执行以下操作:

  • 导入公钥
  • 对密文进行Base64解码
  • 将密文拆分为单个签名块(这里有3个包含相同数据的块:The quick brown fox jumps over the lazy dog
  • 解密每个签名块(m = c ^ e)
  • 连接解密的签名块
package main

import (
	&quot;fmt&quot;
	&quot;math/big&quot;
	&quot;encoding/pem&quot;
	&quot;crypto/x509&quot;
	&quot;crypto/rsa&quot;
	&quot;encoding/base64&quot;
	&quot;bytes&quot;
	&quot;io&quot;
)

func main() {

	pubKeyPem := `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFB
mwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKH
yVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+I
d0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DI
hFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U
1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RC
sQIDAQAB
-----END PUBLIC KEY-----`


	// 导入公钥
	pubKey := ImportSPKIPublicKeyPEM(pubKeyPem);	
	// 对密文进行Base64解码
	ciphertextBytes, _ := base64.StdEncoding.DecodeString(&quot;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&quot;)
	// 将密文拆分为每个签名块(2048/8字节),并解密每个块
	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, &amp;writer, pubKey)
	}
	// 连接解密的签名块
	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 ){
	// 解密每个签名块
	ciphertextInt := new(big.Int)
	ciphertextInt.SetBytes(ciphertextBytesChunk)
	decryptedPaddedInt := decrypt(new(big.Int), pubKey, ciphertextInt)	
	// 删除填充
	decryptedPaddedBytes := make([]byte, pubKey.Size())
	decryptedPaddedInt.FillBytes(decryptedPaddedBytes)
	start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00&lt;data&gt;: 找到第二个0x00之后的索引
    decryptedBytes := decryptedPaddedBytes[start:]	
	// 写入解密的签名块
	writer.Write(decryptedBytes)
}

func decrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int {
	// 标准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

请注意,该代码仅为示例实现,特别是不包括异常处理。


测试:<br>
下面的Java代码

String publicKey = &quot;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFBmwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKHyVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+Id0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DIhFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RCsQIDAQAB&quot;; 
byte[] ciphertext = Base64.getDecoder().decode(&quot;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&quot;);
byte[] decrypted = decryptByPublicKey(ciphertext, publicKey); 
System.out.println(new String(decrypted, StandardCharsets.UTF_8));

使用您发布的方法得到相同的结果。

英文:

From the Java code the padding is not clear, because only the algorithm is specified, but not the padding. In this case the padding is provider dependent, e.g. PKCS#1 v1.5 for the SunJCE provider.

Assuming PKCS#1 v1.5, the combinations Cipher.ENCRYPT_MODE/private key and Cipher.DECRYPT_MODE/public key apply RSASSA-PKCS1-v1_5 as padding. This is functionally identical to signing/verifying with NonewithRSA (except that verifying with NonewithRSA additionally checks the equality of the data compared to decryption with the public key).

NonewithRSA means that the data is not hashed and no digest ID is prepended. This algorithm is actually intended to sign already hashed data (after the digest ID has been prepended). It is in no way meant to sign unhashed data, i.e. the Java code misuses this algorithm.<br>
Since the message size is limited with RSA (key size minus the space required by padding), only appropriately short messages can be signed. Unhashed data whose size exceeds the allowed size therefore forces multiple signatures. This is the reason for the multiple decryption in the Java code.<br>
The use of hashed data is not only useful for practical reasons (signing long messages), but also necessary for security reasons, s. e.g. here and here.

To implement the functionality of the Java code in Go, a low-level implementation is required for signing/verifying in Go as in the Java code.<br>
Another possibility would be to implement the decryption (m = c^e) and remove the padding yourself, which for RSASSA-PKCS1-v1_5 simply consists of a sequence of 0xFF values framed by 0x0001 on the left and 0x00 on the right.

In the following, I consider the second approach. The Go code below does the following:

  • Import the public key
  • Base64 decode the ciphertext
  • Split the ciphertext into the individual signature chunks (here 3 chunks containing the same data: The quick brown fox jumps over the lazy dog)
  • Decrypt each signature chunk (m = c ^ e)
  • Concatenate the decrypted signature chunks
package main

import (
	&quot;fmt&quot;
	&quot;math/big&quot;
	&quot;encoding/pem&quot;
	&quot;crypto/x509&quot;
	&quot;crypto/rsa&quot;
	&quot;encoding/base64&quot;
	&quot;bytes&quot;
	&quot;io&quot;
)

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(&quot;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&quot;)
	// 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, &amp;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&lt;data&gt;: 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
}

with the output:

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

Please note that the code is only an example implementation and in particular does not include exception handling.


Test:<br>
The Java code below

String publicKey = &quot;MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFBmwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKHyVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+Id0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DIhFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RCsQIDAQAB&quot;; 
byte[] ciphertext = Base64.getDecoder().decode(&quot;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&quot;);
byte[] decrypted = decryptByPublicKey(ciphertext, publicKey); 
System.out.println(new String(decrypted, StandardCharsets.UTF_8));

with the method you posted gives the same result.

huangapple
  • 本文由 发表于 2021年8月30日 21:06:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/68984685.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定