Let’s say you have a string that contains both a private SSH key, and the public key, both in PEM format. How do you separate them from each other?
const content =
"Private Key:-----BEGIN OPENSSH PRIVATE KEY-----
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
YourPrivateSSHKeyYourPrivateSSHKeyYourPrivateSSHKey
-----END OPENSSH PRIVATE KEY-----
Public Key:-----BEGIN PUBLIC KEY-----
YourPublicSSHKeyYourPublicSSHKeyYourPublicSSHKey
YourPublicSSHKeyYourPublicSSHKeyYourPublicSSHKey
YourPublicSSHKeyYourPublicSSHKeyYourPublicSSHKey
YourPublicSSHKeyYourPublicSSHKeyYourPublicSSHKey
YourPublicSSHKeyYourPublicSSHKeyYourPublicSSHKey
-----END PUBLIC KEY-----"
One way is to use a regular expression which specifically targets their format. Private keys are almost always contained within a header and footer.
const privateSSHKey =
/-----BEGIN(.+)PRIVATE KEY(.+)(\n.+)*END(.+)PRIVATE KEY-----/.exec(content);
const publicSSHKey =
/-----BEGIN(.+)PUBLIC KEY(.+)(\n.+)*END(.+)PUBLIC KEY-----/.exec(content);
This can be cleaned up a bit:
const privateSSHKey =
/-{5}BEGIN(.+)PRIVATE KEY(.+)(\n.+)*END(.+)PRIVATE KEY-{5}/.exec(content);
const publicSSHKey =
/-{5}BEGIN(.+)PUBLIC KEY(.+)(\n.+)*END(.+)PUBLIC KEY-{5}/.exec(content);
-{5}
exactly 5 instances of-
BEGIN
exact match(.+)
- something could be here, if anything.
matches any character (except for line terminators)+
matches the previous token between one and unlimited times, as many times as possible, giving back as needed (greedy)
PRIVATE KEY
exact match(\n.+)*
*
matches the previous token between zero and unlimited times, as many times as possible, giving back as needed (greedy)\n
matches a line-feed (newline) character (ASCII 10).
matches any character (except for line terminators)+
matches the previous token between one and unlimited times, as many times as possible, giving back as needed (greedy)
END
exact match(.+)
- something could be here, if anythingPRIVATE KEY
exact match-{5}
exactly 5 instances of-
.exec()
executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.
Depending on the format the header and footer may have a varied string:
------BEGIN OPENSSH PRIVATE KEY------
------END OPENSSH PRIVATE KEY------
------BEGIN RSA PRIVATE KEY------
------END RSA PRIVATE KEY------
------BEGIN PRIVATE KEY------
------END PRIVATE KEY------
------BEGIN OPENSSH PUBLIC KEY------
------END OPENSSH PUBLIC KEY------
------BEGIN RSA PUBLIC KEY------
------END RSA PUBLIC KEY------
------BEGIN PUBLIC KEY------
------END PUBLIC KEY------
This is why we need to include (.+)
between BEGIN
and PRIVATE KEY
.
What if the public key was in the ssh-rsa format?
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7jdirkf4o6 ...
You could do:
/ssh-rsa(.+)==/;
The values can then be assigned to a key/value pair within an object, for example:
{
privateKey: privateSSHKey,
publicKey: publicSSHKey
}
Resources:
https://www.thedigitalcatonline.com/blog/2018/04/25/rsa-keys/