Creating RSA Private Key from PFX (PKCS #12) file - encryption

I'm trying to get a private RSA key from a pkcs #12 file.
I've tried running the standard
openssl pkcs12 -nocerts -out priv.pem -in domain.com.pfx
However this results in a key file like the one below:
Bag Attributes
Microsoft Local Key set: <No Values>
localKeyID: 01 00 00 00
friendlyName: xxxxxxxx
Microsoft CSP Name: Microsoft RSA SChannel Cryptographic Provider
Key Attributes
X509v3 Key Usage: 10
-----BEGIN ENCRYPTED PRIVATE KEY-----
The server that I need to put it into canot handle the key file, and when I look at the examples data I see a file like below
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2CF27DD60B8BB3FF
And of cause the key is present in both files.
However it seems the server will only accept RSA Private key file, and it seems to me like the output I get is a X509v3 file, any one know how to get this to an RSA Private key file?

Well - using a text editor to remove the offending lines may be easiest. Otherwise below will clean up the bag attributes:
openssl pkcs12 -in x.pfx -nocerts -nodes -passin pass:123456 | openssl rsa -out privkey.pem
and can also be used to get der/net
openssl pkcs12 -in x-fred.p12 -nocerts -nodes -passin pass: | openssl rsa -outform DER -out privkey.der
which may be in fact the format you want. It is fairly common for tools to not accept a password less private key though (and a lot of tools will silently fail if the # of chars are not at least 4 or 6). So in those cases change the tailend to:
.... | openssl rsa -passout pass:123456 -out privkey.pem
.... | openssl rsa -passout pass:123456 -out privkey.der -outform der

On windows 7 64bit, you can simply use your command.But in mac and linux, you should do the following steps:
1, create your pem file:
openssl pkcs12 -in xxx.pfx -out xxx.pem
2, create your rsa private key :
openssl pkcs12 -in xxx.pfx -passin pass:yourpassword | openssl rsa -des3 -passout pass:yourpassowrd -out xxx.key
this step will create the key file with the conten:"
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,2CF27DD60B8BB3FF"
3, open your .pem and .key file in a text editor, and replace the origin key"
-----BEGIN ENCRYPTED PRIVATE KEY-----" in the .pem file
with the rsa key in the .key file.

This works for me:
openssl pkcs12 -in "$1" \
-nocerts -nomacver \
-passin file:<(cat "$pw") \
-passout file:<(cat "$pw") |
sed -n '/^-----BEGIN ENCRYPTED PRIVATE KEY-----/,/^-----END ENCRYPTED PRIVATE KEY-----/p'

Related

Verifying the password of generated x509 certificate

I have created a x509 certificate. There is a set of openssl commands I used to create it, for example the first command it:
openssl genrsa -passout pass:"$MYPWD" -out privkey.key 2048
where "$MYPWD" is an environment variable where I set the password. After executing this command, how would I check that the password is actually the value of MYPWD environment variable, and not just literally "$MYPWD"?
Thank you everyone in advance!
You must specify a cypher to encrypt the output.
openssl genrsa -aes256 -passout env:MYPWD -out privkey.key 2048
To verify that the password was actually set, simply read back the key:
openssl pkey -in privkey.key
You will see the password prompt.
You can also inspect the content of the privkey.key, "ENCRYPTED"... will be there.
cat privkey.key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,3A2E02985A117F7266F9664420F685B2
...

OpenSSL - Encrypt plain text using RSAES_OAEP_SHA_256

I want to encrypt local plain text file using openssl and RSAES_OAEP_SHA_256 algorithm.
I tried to use the same approach with this blog entry but it did not work.
https://europatech.co.uk/encryption-decryption-with-kms-and-openssl/
$ echo "hello" > plaintext.txt
$ openssl pkeyutl -encrypt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
-in plaintext.txt -pubin -inkey pubkey.pem -out plaintext.bin
-pkeyopt command before -inkey
Usage: pkeyutl [options]
-in file input file
-out file output file
-sigfile file signature file (verify operation only)
-inkey file input key
-keyform arg private key format - default PEM
-pubin input is a public key
-certin input is a certificate carrying a public key
-pkeyopt X:Y public key options
-sign sign with private key
-verify verify with public key
-verifyrecover verify with public key, recover original data
-encrypt encrypt with public key
-decrypt decrypt with private key
-derive derive shared secret
-hexdump hex dump output
-passin arg pass phrase source
am I missing something?
I was looking for the same openssl command and this worked for me:
openssl pkeyutl -in data.txt -encrypt -pubin -inkey Oaep_Pub_Rsa.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 -out enc.pem

Is RSA Encrypt & Decrypt only with Private Key by openssl, correct?

This is my testcase.
$ openssl genrsa -out private.pem 2048
$ openssl rsa -in private.pem -outform PEM -pubout -out public.pem # but I don't use it.
$ touch raw_data.log && echo 123456 >> raw_data.log
$ openssl rsautl -encrypt -in raw_data.log -inkey private.pem > enc.raw_data.log
$ openssl rsautl -decrypt -in enc.raw_data.log -inkey private.pem > dec.raw_data.log
$ cat raw_data.log
$ cat dec.raw_data.log
Why I can encrypt & decrypt data only with rsa private key.(not public key to encrypt data)
Is it correct?
If you read the man page for openssl rsautl, you will find that you can use the pubin option to encrypt using the public key
-inkey file the input key file, by default it should be an RSA private key.
-pubin the input file is an RSA public key.
So you can encrypt either using the private key (default) or the public key (with the pubin option)
openssl rsautl -encrypt -inkey pubkey.pem -pubin -in raw_data.log -out enc.raw_data.log

"No DEK-Info header in block" when attempting to read encrypted private key

I'm trying to read an encrypted PKCS8 private key file. I generated the keys like this:
openssl genrsa -out file.pem -passout pass:file -aes256 1024
openssl pkcs8 -topk8 -inform pem -in file.pem -outform pem -out filePKCS8.pem
And I try reading it in Go this way:
block, _ := pem.Decode(key)
return x509.DecryptPEMBlock(block, password)
But I get an error saying:
x509: no DEK-Info header in block
However, I can't figure out what's going wrong. Am I generating the key wrong or am I using the wrong library? I see libraries specifically for reading unencrypted PKCS8 files but none for encrypted PKCS8 files specifically.
Does anyone have any idea?
Go don't have function to decrypt PKCS8 keys in standard library.
You can this package:
https://github.com/youmark/pkcs8/blob/master/pkcs8.go#L103
A longer explaination for anyone with the same problem.
What would work
Your first command
openssl genrsa -out file.pem -passout pass:file -aes256 1024
generates a PKCS#1 private key file (file.pem):
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1DA219DB746F88C6DDA0D852A0FD3232
AEf09rGkgGEJ79GgO4dEVsArwv4IbbODlxy95uHhfkdGYmuk6OlTpiCUE0GT68wn
KFJfBcHr8Z3VqiHGsXxM5QlKhgnfptxfbrdKErgBD5LQcrvnqmf43KeD4lGQcpiy
...
...
mAKMCwiU/GKZz8ZwQ4qGkBlVVCOFfgwmfbqguJF2l8yzM8lYI9MZ9NEwKkvEbc
-----END RSA PRIVATE KEY-----
This private key file can be parsed and decrypted by x509.DecryptPEMBlock() alright.
What would not work and why
Your second command
openssl pkcs8 -topk8 -inform pem -in file.pem -outform pem -out filePKCS8.pem
converts that file into PKCS#8 format (filePKCS8.pem).
The subcommmand genpkey would directly produce a similar result:
openssl genpkey -algorithm RSA -aes256 \
-pkeyopt rsa_keygen_bits:1024 -out filePKCS8.pem
The generated filePKCS8.pem (either way) would look similar to this:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIISrTBXBgkqhkiG9w0BBQ0wSjKpBgkqhkiG9w0BBQwwHAQIKL+ordsVfqsCAggB
MAwGCCqGSIb3DQIJCQAwHQYJYIZIWAUDBAEqBBCipOAAxWkC0/zkNLNYTSMgBIIS
...
...
zfdxjZ0XmPiwED2azsLMnRrWnRj2UqMtnv9zO/ucik9za
-----END ENCRYPTED PRIVATE KEY-----
x509.DecryptPEMBlock() does not support this format. And as specified in #8860, the Go's core library has no real plan to support pkcs#8 in the near future.
As mentioned by Gregory, if you want to work with it, you'll have better luck with 3rd party library like github.com/youmark/pkcs8 (Documentation).

How can I encrypt data with a public key in Node.js? [duplicate]

This question already has answers here:
Encrypting data with a public key in Node.js
(6 answers)
Closed 2 years ago.
In crypto, I see only Signer/Verifier for doing digital signature and Cipher/Decipher with symmetric key encryption.
How do I encrypt data with public key?
As mentioned in the official nodejs api docs here:
crypto.publicEncrypt(key, buffer)
Encrypts the content of buffer with key and returns a new Buffer with encrypted content. The returned data can be decrypted using the corresponding private key, for example using crypto.privateDecrypt().
If key is not a KeyObject, this function behaves as if key had been
passed to crypto.createPublicKey(). If it is an object, the padding
property can be passed. Otherwise, this function uses
RSA_PKCS1_OAEP_PADDING.
Because RSA public keys can be derived from private keys, a private
key may be passed instead of a public key.
So the answer is:
var encrypted = crypto.publicEncrypt(publicKey, buffer);
You might be interested in my NaCl bindings. From its API:
// Encrypt and sign
box(message, nonce, pubkey, privkey)
// Decrypt and validate
unbox(box, nonce, pubkey, privkey)
// Generates a new keypair, returns {private: <buffer>, public: <buffer>}
boxKeypair()
// Lengths of nonces and public and private keys in bytes
// { nonce: x, pubkey: x, privkey: x }
lengths.box
Yet another approach is using Cryptographic Message Syntax (CMS). It's not a pure Node.js solution, but you likely have all tools you need in the box. Below is the example using OpenSSL:
Generate x509 certificate (recipient) and private key files (in Bash):
openssl req -nodes -new -x509 -keyout key.pem -out cert.pem
Encrypt/Decrypt message from standard input (in Bash):
echo 123 | openssl cms -encrypt -recip cert.pem | openssl cms -decrypt -inkey key.pem
You can use -in/-out parameters to work with files. Below is an example you can use for Node.js:
require('child_process').execSync("openssl cms -encrypt -in file.json -recip cert.pem -out file.json.cms")
On Linux you'll likely have OpenSSL installed already. You can get OpenSSL on Windows by installing Git Bash, although you can also use built-in PowerShell commands. You'll need to generate a PFX certificate (using New-SelfSignedCertificate) or install existing one (can be generated with OpenSSL too). Once the certificate installed in the certificate store, you can use below commands for encryption/decryption:
Protect-CmsMessage -to CN=MyCertName -Path file.json -OutFile file.json.cms
Unprotect-CmsMessage -Path file.json # It will find proper cert in cert store for you
Below is an example how to generate .pem and PFX certificates from the same private key using OpenSSL, and make messages interchangeable between OpenSSL and PowerShell.
Generate certificate with extensions (that's required on Windows):
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem -subj '/CN=MyCertName' -addext extendedKeyUsage=1.3.6.1.4.1.311.80.1 -addext keyUsage=keyEncipherment
The above snippet will work only for newer versions of OpenSSL (1.1.1). Otherwise you need a separate file to define extensions. Then generate a PFX certificate (protect it with some password):
openssl pkcs12 -export -out certificate.pfx -inkey key.pem -in cert.pem -passout pass:P#ssw0rd
Then copy that PFX file to your Windows machine. You should be able to install it via PowerShell (Import-PfxCertificate) or manually (click on it and follow wizard, use all defaults). In order to make messages interchangeable use the -inform \ -outform parameter when using OpenSSL. For example:
openssl cms -encrypt -in file.json -recip cert.pem -outform PEM
openssl cms -decrypt -in file.json.cms -inkey key.pem -inform PEM
# If having both OpenSSL/PowerShell on the same OS, use this for testing:
echo test | Protect-CmsMessage -to CN=MyCertName | openssl cms -decrypt -inform PEM -inkey key.pem
Btw, the CmsMessage commands will be available on PowerShell Core 7.1, so you can use it on Linux/Mac too (it's in preview now, and a stable version will be released in Dec 2020).

Resources