Not too long ago, I wanted to know how to generate the public-keys that OpenSSH generates, as a transitional step to understanding how to decode them. In this fashion, I might apply the knowledge, some day, to a dynamically configurable SSH platform to allow a client to connect via SSH and to authenticate against a database, such as with Github and Bitbucket.
What I did not learn while painfully trolling and reverse-engineering all of the key-generation code for ssh-keygen was that this representation is described by PKCS8. Yes, more than a little time was unnecessarily wasted. In fact, you can generate PKCS8-formatted public keys with OpenSSL.
Needless to say, I never finished reverse-engineering the code. This wasn’t so much because it became a monster, but rather the code was unfathomably ugly. It would’ve taken an enormous amount of time to hack something together, and the same amount of time to refactor it into being something elegant. It required too much of a commitment for something without an immediate need. It would’ve been quicker (and funnier) to write a FUSE wrapper to read the database, and just point OpenSSH to the mountpoint.
Generating an RSA public-key and converting it to PKCS8:
$ openssl genrsa -out mykey.pem 2048 Generating RSA private key, 2048 bit long modulus .................+++ .........................................................................+++ e is 65537 (0x10001) $ openssl rsa -in mykey.pem -pubout | ssh-keygen -f /dev/stdin -i -m PKCS8 writing RSA key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCb7G51EdPBy8Np3x84DoWB5moC/ijLqDKr7ipvajNs6rICIEgX70D5S5jPAiC7HCcubHbxAEV3rRlQJpsKyiy85vKHL787IRhmHu9ILFRm+7OxYY783QCBNP+NcZJVFWsHASxm05hOB8Z4pC0d2ql/eajqUOvk83TdiJnJA3lg+3/LCTd6mfQAKybycllBZxE8W6FLXlpsva2J1hW3bxs5FcvsoqzVjboPmbXNuC0sKk5gWPq/Rrpc7E9N8bEPt/jk/CAUtUPxFtFMe48odHvXnb4YAkt2sTKHzH9BWgn4jSjPsjwYBiG2xWk0n5RcAi2GoPHCwveD2rArY+fQW8+5
The parameters to ssh-keygen simply indicate that the data is coming from STDIN, we’re doing an import, and the key-format is PKCS8.
Also, with DSA:
$ openssl dsaparam -out dsaparam.pem 2048 Generating DSA parameters, 2048 bit long prime This could take some time ..............+.........+.................+...........+++++++++++++++++++++++++++++++++++++++++++++++++++* .......+....+...........+......+...+................+.....+.....................+...+...................................+..........+....+..........+.........+..+.+...........+.....+..+......+.......+.....+........+.............+.....+.....+...+..+..............+++++++++++++++++++++++++++++++++++++++++++++++++++* $ openssl gendsa dsaparam.pem -out dsa_priv.pem Generating DSA key, 2048 bits $ openssl dsa -in dsa_priv.pem -pubout | ssh-keygen -f /dev/stdin -i -m PKCS8 read DSA key writing DSA key ssh-dss AAAAB3NzaC1kc3MAAAEBAMq+cozwNedgZotyF85hu2yTtdm2EPQhZkSR3iC1qsidkO99HTt4Gpx5vrkdPs13D/RSJj7EJYwvsWSOI/OgY+OsqymR7Erqpf0NGdwzHpTz8nYe2oQNZgpaxh9iTMsfCQwdfchGT4QwewVf4fAGXRZRtmTSbNZIXOJMBiI9h6qW29DvI1TH/x4iWL3j1XA6NDGbVECYU4CE3bQUt/F3wuYTcy6JZU9JzbCLwO6lIkFQmVk4HyMODwM5YKectFh38a7r18oTosnewu9bKoiXCVmOK6RoEgiz/+Sqjxgi8GZ/LeJtLJGxPZxuUmRe8HGMprNW4VmaxoRkNgVL5LoyBNkAAAAVANmGyUL5j1iOp5ABkqKJuiq1sqEXAAABADzHG6NVAzVvZ8xFHc4G2gs56/HvkmvsyKyyQE5o1sV5Yp9yZq9LDW6egrCSRi1Ny6PeBCuSBPU1piZwObX7ZDJCvMvQZf55EONuZYVYBhYvV0Cxw0aet94Qz/u9RA9h1CKl7321d8SDWw4DDNAmQ7nS+NuS6bkAV9djpzK8WFh6PHjARF4DdefbjaYIVig8iWxxu3qju1iQQta2/XZ23OJxZb8eUE+Dgeq5Qdosb508VIRPByovRL3o9RbQ2y50Zp2OXmbib94nW1CpFzo/84RQfnP3RG2LPpmeK+KBTqbctj43B+ATvuIw5vHYj67o3P1MgOHvFpGnDt/McdUo1BoAAAEACqjSYFC9Zj5w5P2uMRhj+o9Gc7z3bYC/OphTcWhjZSs2OAF8+PGjpEjQYSpHPmbLhdbPsZpf2NAnAtz1WxCRVvOFeuSl9zdp4/JeRj3SKrxk0L/r5ZPGCkx+FdWV65sSwK8usaFHyKXeges1N8nmzTegphW3xVb4qI9OazanQ5sxqr+TzDa2yRAMK/PwW8mxyaYkofyct7uHOR0CD6/WjkYHHOEDzubPo1/nh2oKGC2eQnluNP8xBAg7Z5sqm6ZBSIWmOhpaOgIDNcwYla9gJJHrMecgbHkb6HuPcpaJvd2dCZpujFfB0+2jFUgPUsgygIMfV5mjUI3Zajmgmwtqiw==
I included DSA because generating a key-pair with DSA for general PKE is a bit more obscure. I don’t know why. It is still possible, however.
Lastly, ECDSA (elliptic-curve DSA), for completeness. This is really the one that you want to be using, if given a choice. See how cute/short the public-keys are for an algorithm with considerably-more strength? A 256-bit curve is equivalent to a traditional 3072-bit RSA key.
$ openssl ecparam -genkey -name prime256v1 -noout -out prime256v1.key.pem $ openssl ec -in prime256v1.key.pem -pubout | ssh-keygen -f /dev/stdin -i -m PKCS8 read EC key writing EC key ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC3FrhznL2pQ/titzgnWrbznR3ve2eNEgevog/aS7SszS9Vkq0uFefavBF4M2Txc34sIQ5TPiZxYdm9uO1siXSw=