-
Notifications
You must be signed in to change notification settings - Fork 18k
crypto/x509: insufficient validation in x509.DecryptPEMBlock leads to decryption false positives #10171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
To really verify the password, the function needs to verify As the function only returns the decrypted pem block, I think it's possible to construct a PEM that can be decrypted IMHO, this is working as intended. PS: your openssl example can detect the password is wrong |
Looking at the openssl output more carefully it does seem that they are just going through all the RSA private key parsers and trying to see if it matches any of them, before bailing. It seems that to achieve what I want to do in Go I will have to do the PEM decoding and then try to parse it using the available formats: func checkPassword(pem *pem.Block, password string) {
key, err := x509.DecryptPEMBlock(pem, []byte(password))
if err == nil {
validKey := false
_, err = x509.ParsePKCS8PrivateKey(key)
if err == nil {
validKey = true
}
_, err = x509.ParsePKCS1PrivateKey(key)
if err == nil {
validKey = true
}
if validKey == true {
fmt.Println("Valid password found: " + password)
}
}
} I'm ok with closing this as a "works as intended" with the caveat that this might be confusing for other people too. Maybe a source-code comment indicating this potential caveat would be appropriate? Not sure if it is a contrived example someone decoding an encrypted PEM but not actually trying to parse the private key. |
The problem is that there might be private key encodings that Go The docs is also correct, technically: The condition for returning IncorrectPasswordError is not "if password I will propose a CL to add one sentence after that: |
Perfect. Thank you @minux. |
The change 7603 is not submitted yet, re-open. |
Note that this problem arises because of deficiencies in PEM encryption. Although PEM encryption may be needed to support reading existing keys, it shouldn't be used in anything new. Putting together scrypt[1] and secretbox[2] will be far stronger and won't have this problem. [1] https://godoc.org/golang.org/x/crypto/scrypt |
The validation of
x509.DecryptPEMBloc
seems to be insufficient and any password that matches the padding validations in (https://golang.org/src/crypto/x509/pem_decrypt.go) provides a non-error return.The following code shows two different passwords decoding the same encrypted PEM file successfully. The correct password for the encrypted PEM file in privateKeyString is "omgomgponies".
The correct password can be verified using openssl (
omgomgponies
):openssl rsa -in private.pem -outform PEM -pubout -out public.pem Enter pass phrase for private.pem: writing RSA key
And we can also demonstrate openssl returning an error for the invalid password (
ruvf
):openssl rsa -in private.pem -outform PEM -pubout -out public.pem Enter pass phrase for private.pem: unable to load Private Key 140735220982608:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1180: 140735220982608:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:365:Type=RSA 140735220982608:error:04093004:rsa routines:OLD_RSA_PRIV_DECODE:RSA lib:rsa_ameth.c:119: 140735220982608:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1180: 140735220982608:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:365:Type=PKCS8_PRIV_KEY_INFO 140735220982608:error:0907B00D:PEM routines:PEM_READ_BIO_PRIVATEKEY:ASN1 lib:pem_pkey.c:141:
Found while trying to create a PEM cracker: https://github.com/diogomonica/go-pemcrack
The text was updated successfully, but these errors were encountered: