reading Ed25519 key from env variable to sign/verify a JWT - ruby

I am trying to sign (and later verify) a JWT. The issue I have is that there will be multiple servers running and one can sign a JWT and others need to verify. So I can not internally generate a key pair. Our devops would generate the keys store them in a secrets manager and put them as an env variable. I am trying to read the env and create the private key object
My issue is that the key generated by
ssh-keygen -t ed25519
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIPtNTjzDd8/b8asuFRpkrmbmraj3xinurMHoTQFYUMLa
-----END PRIVATE KEY-----
Assuming I put this in an env variable env.key
how do I get the ed25519 key in ruby, neither of the below options seems to work.
#option 1
private_key = RbNaCl::Signatures::Ed25519::SigningKey.new(env.key)
#option 2
private_key = RbNaCl::Signatures::Ed25519::SigningKey.new(Base64.decode64(env.key))
token = JWT.encode payload, private_key, 'ED25519'

Related

SSL Private Key Hash Mismatch After Retrieval from Secrets Manager

Situation:
Currently SSL public key (public.key1) and private key (private.crt1) file both on EC2 A, and stored both value separately in Secrets Manager named "public——key" and "private_key" manually with plaintext based on this link https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-ranger-tls-certificates.html.
On EC2 B, able to retrieve both key value with aws cli as below:
Public Key:
aws secretsmanager get-secret-value --secret-id public_key --query 'SecretString' --output text > public.key2
Private key:
aws secretsmanager get-secret-value --secret-id private_key --query 'SecretString' --output text > private.crt2
However, when use sha256sum check both key value, private key output both different, public key output are the same.
EC2 A:
sha256sum private.crt1
EC2 B:
sha256sum private.crt2
These two outputs are different.
What I tried:
copy both file on local and use VS studio to compare both file, no output or hightlights
Used openssl match command to check if both private key file with below command, but same output.
openssl x509 -noout -modules -in private.crt1/private.crt2 | openssl md5
Can anyone help me with this?
Goal:
Trying to test these commands to extract correct keys then put in EC2 user data.

How to read/write SSH Private key (id_rsa)

As part of an automated Cloud Init setup, I am auto generating public/private keys for users, reading them from file and then saving them in bash variables like so
public_key=$(cat /path/to/id_rsa.pub)
private_key=$(cat /path/to/id_rsa)
Then I write them to the target machine through Cloud Init like so
- sudo -H -u aryan bash -c 'echo "$public_key" > ~/.ssh/id_rsa.pub'
- sudo -H -u aryan bash -c 'echo "$private_key" > ~/.ssh/id_rsa'
The public key is written correctly, but the private key is written to a single line and then SSH complains that it is the wrong format. I am expecting this
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCpOipW5Xyjc9jLE6AX/0HktpZtyokJap9k5njJl3uw7VpcUITW
3UzHHZor4b4N1x8wp17Y0udPsrcPtfJR+pVSr0s6ZMkjX0B7J5jE64iPlVOkO+ww
b4CMlonViWeTJ/+gSLkfC2EDfSqPTEOWx44Vs7Mt2qi5Rvq/Po81NDrK2QIDAQAB
AoGAcklZ9r2dYzYFn4BtikdVVQUKqrMxwS5E33vW7y5i1qY1dErcq89g3shbKm+W
TvqNkeo23+/vT5++idmzATJeTQ+uhRidPrU6XTWd4I8LvHB6dYIGKpGuciv4NWG0
3CLDt5IRLpAJ8qAl3tmitWadZw7lJtGAWg+7zdbIoP07XhECQQD32vBAwePlB/ZY
CsRNeIDUWtAGaxqBvssmbh4wfCYZDH+3BJbyMG0AWycE0YLZLlACKzTUu5PC8CKu
zQBKb02LAkEArsnGdJ7ipDTZZWl1Q42M494SfQUA9+he12WU6O2o2BJqr8cVRG2V
BJHHXvdHB+xWRMpo0vxTiGdDIDqPwfPdqwJBAMBpkgvjuYSqur48lYpC21h/q3Dg
IrLIqDMMV5lyN61Ie7lb8cbQez5EhTUDZN4vSuN0IU5o1FwIShSDhw9B+uMCQFwN
UiJLJ0uZtcCOCL76BnBfnVcQUpE9ZO2FxyXhPGIHWP6YF6BBIhEVAW4HRvZqRojW
HNy5HPkigRyxGtLnrx8CQFWZtrGiBIrYRsrf9fwXv4DTB5z7sQLEf8x2dwvif34O
+bYMoDJPewr3ti88KJP4rubmIS9PTCAJxEfMBPkZHvE=
-----END RSA PRIVATE KEY-----
But instead I have this (truncated)
-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCpOipW5Xyjc9jLE6AX/0HktpZtyokJ...
Question: How do I correctly read a private key into a variable and then write it to a text file
Note: The easiest way would be to simply copy the file but I don't think Cloudinit supports cp/scp. If it does, please do let me know how
You need to quote your command substitution to preserve newlines:
private_key="$(cat /path/to/id_rsa)"
What you can do for cloud-init ssh setup, is to generate the private and public key before the deployment and then use cloud-init to deploy the servers with those ssh keys.
This way, you will always have the same private key on your computer and be able to ssh into the new servers.
Also it might be a security issue if the wrong people have access to the cloud-config file
Sample code:
ssh_authorized_keys:
- ssh-rsa AAA... user#server
ssh_keys:
rsa_private: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpwIBAAKCAQIA3FurAzWIiBuNd1ew2sM3s/eOg+Sf9nSQPcEzNyNTkhxSwkxf
3fgNlSpoBc1s7XD9DefpzGT/lxZzVQcQGJ7NnxddRKOH8Uhhp75L3Q18L4z4bZNM
zX5ngtZopa4SoFWiMCVljXeWy4CpuQdpD8N9Bpb+9IYCVOzitnrD2UM2ubf6imOq
Saeiyi3/SdftcUO3uhjemLkg9d2nwvfbJUqSFR4NGR5nsOxxMC4tnxylDRN88qE3
fSrSQHY+qTu+3mKQ6J7VKUM7e0jRD/vQK64V0f6AqKLxta7XFeA8sIa0qbGNQHBk
Zg+OOFYUz4x0qbwmwuQR9RS6HnBLXvdcZb36nXkCAwEAAQKCAQEfx+jGMbZbSv4A
NFmBc55ZCl83joWzmeQjw/WLAkFPVV5qP3GkJd5voQoXrCUFqcIVe1kw7XAfblF7
9eTQaDbntwrwl1VH61SKSNvQKd27Tf2WgCQXjx+Gsz2sh4qQLUmTABHBcXoCJ7BS
y0rPxzYE+UoUIi+7595ayyHr99Gwv1/N78xw7PS+oyxmn4rsbFYfWbkKWKgbizAm
oxM5EE1g1Mn9m0ocruYzTiPIHLGMsfeqMDzHG7lK0rTL0nqFP/QegZkSE0hQ/fJm
gS44NnFQ1HeQB3GCbgJlQFNVNHPueZevEemZ5QEuPIhYmG8+GlGRl9aFto9BGDa7
z0Ct29HeAQKBgQ95Z86CIZIsSWhjt0ZjW0DzFd6JQC+gKxmxcaELZPL+M0jh2zMV
9jCIPERV4RKwzttKm/tGz2Zh+FsToi0Ie1TW4uVArGcFeX+XsTIrcIyIwzoFixR1
k2Rv9ZwJGQgapTokhoVidAMRUIZfN/2HH4y2ZnIdOUDpP8FpknFiTXFoEQKBgQ49
hWHFwKFB6sprKq+dJkFgNEhtdn4q0K5NrBgwHm6h2sO3tyIwVMCmhwHtBnEQOovg
W7dM/GYqpxE76qaJBoHFht0RGPxt1wbQRbjwZ78KdMrLa+RZlFRVdPU5QXEcYu+H
jqIiTf/aDl69cdQ8dkJoGwjjT80R4t2zy+7iKqqG6QKBgQbqYhsniytRgYkWr2zU
sI6pVMe3nSPrt/dmlvq7JeV296Kf1bnSAdGUwSJlIw6AWCInCOjWr4/5Ds5dSuhH
Vx8GXibIrYPpLXB5caaTRVx5Lo66tXpyRWnoo2KVqks15UvD0R7BbkmErnEvEs3K
Wq4/Qi+Toe3Blk2xCdKEdUnOkQKfgQLZXC5LmlapEYieGFQ6ZMT/snYrMGHdvxKg
h6XvOqd3yoUN5J36fXpt1uUTvw4v6QbDRJZP2M+4COTxz+ix0ZN1KZ5hJVabw0Gh
udFeh+M4/FT2jgeJxJt63YOSiP1QaJrzzB20L1bZEbbywCtuTVrL6VzF3dlxkqo4
pryMk2y6wQKBgQ3MpmrMTRS3bA7h6qMvaZep6Pke6gsXSgGpbU9mFB2ja8IKIVLZ
iVLjmcN1ItqKtYbD01WURkcV3ne+E9bbDYrBQmPDfaO+VbUgBVTjmybLpamrci5k
DcDQVCymHy0EwAqGOuWKM8EgbxuTKDGuUX9Q0TI23fwTc9rB6j3FEAnyvQ==
-----END RSA PRIVATE KEY-----

convert ed25519 private ssh key to RSA private key

I'm looking to convert an ed25519 private key to an rsa private key using ssh-keygen.
I found this helpful guide but I am having trouble figuring out how to specify that the input format is ed25519 and the export format should be rsa.
I've tried a bunch of different ways trying to match the synopsis and the description of flags, but every time I try, I get "Too many arguments" error from ssh-keygen.
I'd also like to find the command to generate a public key from a ed25519 private key to verify that it works.
No, it can't be converted. RSA and EdDSA are not just different types of keys, these are totally different Cryptosystems. Key generation algorithms, private keys are just part of it.
All the conversion options available in ssh-keygen are usually convert one type of RSA key to another type of RSA key. e.g. converting OPENSSH RSA key to PKCS8 RSA key. Basically, that so called conversion is just packaging RSA key in different ways.
As mentioned in "How to generate secure SSH keys", ED25519 is an EdDSA signature scheme using SHA-512 (SHA-2) and Curve25519
The main problem with EdDSA is that it requires at least OpenSSH 6.5 (ssh -V) or GnuPG 2.1 (gpg --version), and maybe your OS is not so updated, so if ED25519 keys are not possible your choice should be RSA with at least 4096 bits.
To generate the private key:
ssh-keygen -t ed25519 -P "" -f myid_ed25519
From the private key, you can generate its public key (which has nothing to do with RSA):
ssh-keygen -y -f myid_ed25519 > myid_ed25519.pub

Setting CF environment variable with multiline value

I want to set a RSA token in environment variable of CF App.
I try to set it with below commands
export var1=`cat key.pem`
cf set-env app KEY "$var1"
If I console the env variable(cf env app), I get the expected output:
.
.
User-Provided:
KEY: -----BEGIN RSA PRIVATE KEY-----
.
. multi-line key contents
.
-----END RSA PRIVATE KEY-----
However, if I run the app, it fails in the authentication.
I also tried applying quotes:
cf set-env app KEY "'$var1'"
It was the token issue.
The first approach mentioned in the question worked.

Invalid OpenSSH key format when importing an ec2 key form an existing one

I am using the ruby EC2 SDK, Version 2. The private key material of a key generated with EC2 is stored in a string. I am trying to generate the public key material that is necessary to import the key into EC2 using OpenSSL::PKey::RSA
After that I am trying to import the key pair.
It looks like this:
kk=OpenSSL::PKey::RSA.new my_private_key_material
pub=kk.public_key
ec2.import_key_pair({key_name: "my_key", public_key_material: pub.export})
The API is throwing this error:
*** Aws::EC2::Errors::InvalidKeyFormat Exception: Key is not in valid OpenSSH public key format
I am not sure what is wrong and how to generate the public key material correctly. I already tried to Base64 encode the public key string without success.
Edit
I tried a couple of new things.
I generated a new key using the EC2 web console from scratch and then geneerated the public one the way Raphael points out below with
openssl rsa -in mykey.pem -outform PEM -pubout -out mykey.pub
The key is not encrypted.
Whey trying to import the public key, either with the web console or by code, I get the same error.
Edit 2
I found this.
When generating the public key with a different command, it works:
ssh-keygen -y
The generated public key looks different. It starts with
ssh-rsa AAAAB3NzaC1yc2EAAAADA....
While the first generated one starts with
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG....
Now the question is how to generate the first format in ruby. I also found this post on different formats.
OK, I solved it by following this post.
It turned out the public key had to be generated in a different way
kk=OpenSSL::PKey::RSA.new my_private_key_material
key=kk.public_key
type = key.ssh_type
data = [ key.to_blob ].pack('m0')
openssh_format = "#{type} #{data}"
ec2.import_key_pair({key_name: "my_key", public_key_material: openssh_format})
The documentation suggests that key contents must be encoded in Base64 client-side, however this is not the case: The SSH key contents should be provided as-is, in the format "ssh-rsa XXXXX....".
Rory is right. In NodeJS below code worked.
let keypair = fs.readFileSync(homedir + '/.ssh/id_rsa.pub');
result = await ec2.importKeyPair({
KeyName: 'KeyPairName',
PublicKeyMaterial: keypair,
}).promise();
I m using Ruby SDK V3 and this is work for me to import key to AWS
#!/usr/bin/env ruby
require 'rubygems'
require 'aws-sdk-ec2'
key_content = File.read('/home/xxx/keys/sshkey.pub')
ec2_client = Aws::EC2::Client.new()
resp = ec2_client.import_key_pair({
dry_run: false,
key_name: "test-ruby-key",
public_key_material: key_content,
})
Hope it helpful!

Resources