如何用Go实现Java风格的RSA公钥解密?能否通过Go Crypto库的RSA-PSS验证获取解密载荷?
Let's break down what's going on here first, then fix your Go code and answer your question about RSA-PSS.
Why Your First Attempt Failed
Your initial Go code has two critical issues that led to failure:
- You tried parsing a public key using
x509.ParsePKCS1PrivateKey—that function is for private keys, not public ones! You need to use the correct public key parsing utilities. - Your manual RSA logic was incomplete, especially around handling segmented data (just like the Java code does for 2048-bit RSA keys).
Understanding the Java Code
First, let's clarify a key point: "RSA public key decryption" isn't standard RSA encryption/decryption (where public keys encrypt, private keys decrypt). What your Java code is doing is decrypting data that was encrypted with an RSA private key (a non-standard way of encoding or "signing" data) using the matching public key. This works because RSA's mathematical operations are symmetric:
- Private key encryption:
ciphertext = plaintext^d mod n - Public key decryption:
plaintext = ciphertext^e mod n
The Java code handles 2048-bit RSA keys by processing data in 256-byte chunks (since 2048/8 = 256), which is necessary because raw RSA can only process data up to the key size in bytes.
Correct Go Implementation
Here's the equivalent Go code that matches the Java logic, including chunked processing for 2048-bit RSA keys:
import ( "crypto/rsa" "crypto/x509" "encoding/base64" "fmt" "math/big" "os" ) func decryptByPublicKey(encryptedData []byte, publicKeyStr string) ([]byte, error) { // Decode Base64-encoded public key keyBytes, err := base64.StdEncoding.DecodeString(publicKeyStr) if err != nil { return nil, fmt.Errorf("failed to decode public key: %w", err) } // Parse public key (handles X.509 format, matching Java's X509EncodedKeySpec) pubKey, err := x509.ParsePKIXPublicKey(keyBytes) if err != nil { // Fallback to PKCS#1 format if X.509 parsing fails pubKey, err = x509.ParsePKCS1PublicKey(keyBytes) if err != nil { return nil, fmt.Errorf("failed to parse public key: %w", err) } } rsaPubKey, ok := pubKey.(*rsa.PublicKey) if !ok { return nil, fmt.Errorf("public key is not an RSA key") } keySize := rsaPubKey.Size() // 256 bytes for 2048-bit RSA var decryptedData []byte offset := 0 inputLen := len(encryptedData) for inputLen-offset > 0 { var chunk []byte if inputLen-offset > keySize { chunk = encryptedData[offset : offset+keySize] } else { chunk = encryptedData[offset:] } // Perform raw RSA public key decryption: ciphertext^e mod n ciphertextInt := new(big.Int).SetBytes(chunk) plaintextInt := new(big.Int).Exp(ciphertextInt, rsaPubKey.E, rsaPubKey.N) // Append the decrypted chunk (leading zeros are handled implicitly) decryptedData = append(decryptedData, plaintextInt.Bytes()...) offset += keySize } return decryptedData, nil } // Example usage func main() { pubKey := os.Getenv("PUBKEY") encryptedPayload := []byte(/* Your encrypted data here */) result, err := decryptByPublicKey(encryptedPayload, pubKey) if err != nil { fmt.Printf("Decryption failed: %v\n", err) return } fmt.Println("Decrypted data:", string(result)) }
Can You Use RSA-PSS Verification to Get the Payload?
Short answer: No, not for your use case.
RSA-PSS is a standard signature verification algorithm—it only checks if a signature matches the hash of a known payload. It does not recover the original payload itself. Your Java code is performing raw RSA decryption to retrieve the full original data, which is a different operation than signature verification. Since your service provider explicitly states no private key is needed, they're using this raw RSA private-key-encrypt/public-key-decrypt pattern, so you need to stick with the manual exponentiation approach above.
内容的提问来源于stack exchange,提问作者Kevin Kaburu

