Haskell中从PEM Base64编码字符串生成公/私钥问题求助
Hey, that StreamConstructionWrongSize error is super common when dealing with X509/PEM parsing in Haskell—usually boils down to issues with how you're handling the PEM data or ASN.1 decoding. Let's break down the most likely fixes and checks you can run:
1. Verify your PEM data is intact and correctly formatted
First, double-check that your Base64-encoded PEM string has:
- The correct header/footer pairs (e.g.,
-----BEGIN CERTIFICATE-----and-----END CERTIFICATE-----for X509 certs, or-----BEGIN RSA PRIVATE KEY-----for PKCS#1 private keys) - No extra whitespace, line breaks, or truncated Base64 content
- No non-ASCII characters (PEM is strictly ASCII-based)
You can quickly validate this with OpenSSL: save the PEM string to a file and run:
# For certificates openssl x509 -in your-cert.pem -text -noout # For RSA private keys openssl rsa -in your-key.pem -text -noout
If OpenSSL throws an error, your PEM data is corrupted—fix that first before debugging your Haskell code.
2. Ensure you're parsing PEM correctly with Data.X509.PEM
It's easy to skip a step when extracting the actual X509 object from the PEM wrapper. Here's a robust example of parsing a certificate:
import Data.X509 import Data.X509.PEM import qualified Data.ByteString as BS import Data.String.Conversions (cs) parseX509Cert :: String -> Either String X509Certificate parseX509Cert pemString = do -- Convert String to ByteString (cs handles ASCII correctly here) let pemBS = cs pemString -- Parse PEM blocks pemBlocks <- case pemParseBS pemBS of Left err -> Left $ "Failed to parse PEM: " ++ err Right blocks -> Right blocks -- Filter for the certificate block (match the header label exactly) certBlock <- case filter (\block -> pemLabel block == "CERTIFICATE") pemBlocks of [] -> Left "No certificate block found in PEM data" [block] -> Right block _ -> Left "Multiple certificate blocks found—expected one" -- Decode the signed X509 object signedCert <- case decodeSignedObject (pemContent certBlock) of Left err -> Left $ "Failed to decode X509: " ++ show err Right obj -> Right obj -- Extract the actual certificate from the signed wrapper Right $ signedObject signedCert
For private keys, adjust the label to match your format: use "RSA PRIVATE KEY" for PKCS#1 keys, or "PRIVATE KEY" for PKCS#8 keys.
3. Fix common encoding mismatches
The StreamConstructionWrongSize error often pops up when you're using the wrong encoding to convert between String and ByteString. Since PEM is ASCII-only, Data.String.Conversions.cs should work, but if your input String has hidden non-ASCII characters (like smart quotes or invisible whitespace), that'll break the Base64 decoding.
Try explicitly converting with ASCII encoding instead to rule this out:
import Data.ByteString.Char8 (pack) let pemBS = pack pemString -- Pack String to ByteString using ASCII encoding
4. Use the right cryptonite functions for private keys
If you're working with private keys, make sure you're using the correct import function for your key format:
- For PKCS#1 RSA keys: Use
Crypto.PubKey.RSA.PKCS1.importKey - For PKCS#8 RSA keys: Use
Crypto.PubKey.RSA.PKCS8.importKeyPair
Using the wrong function will lead to ASN.1 parsing errors like StreamConstructionWrongSize.
If you can share a bit more of your full code (or a sanitized version of your PEM data), I can help narrow this down even further!
内容的提问来源于stack exchange,提问作者blue robot

