#
lokey is a tool that makes it easy to work with and convert between cryptographic key formats.
Named after the shape shifting and mischief-making Trickster from Norse mythology, this tool serves to test the bounds of possibilities and order.
The fastest way to get lokey is to use pip:
$ pip install lokey
lokey makes it easy to fetch cryptographic keys from public sources like Keybase and PGP keyservers, for example:
Fetch my Keybase key using my Twitter handle:
$ lokey fetch keybase twitter:jf
Search for PGP keys from journalists at the New York Times:
$ lokey fetch pgp nytimes.com
You can see all of the fetching commands that lokey has by typing:
$ lokey fetch
lokey is also a tool for converting between cryptographic key formats, for example
Make it easier to grant your friends access to your SSH server:
$ sudo adduser jf $ mkdir ~jf/.ssh $ lokey fetch keybase twitter:jf | lokey to ssh > ~jf/.ssh/authorized_keys
Send an S/MIME encrypted email to an administrator of a TLS secured webserver:
$ echo "A ship journeys from the east, Muspell's people are coming" > message.txt $ lokey fetch tls example.com > example.com.pem $ openssl smime -encrypt -des3 -in message.txt example.com.pem > smime.p7m
One of the administrators of the TLS secured webserver could read the message using this command:
openssl smime -decrypt -in smime.p7m -passin pass:[password for key] -inkey /path/to/webserver.key
lokey will also give you information about keys that you pipe into it:
$ cat ~/.ssh/id_rsa.pub | lokey
At the moment, lokey can convert RSA keys between the following formats: openssh, X.509 Certificates, PGP, and JWT.
With lokey you can:
- Use the public SSL certificate of a website to send an S/MIME encrypted email to any website owner that uses TLS:
- Grant access to your a server by turning your friend’s keybase key into an openssh key
The genesis of this project comes from the many conversations I had with my dad about his implementation of OpenPGP in Common Lisp. One of those conversations was when I first learned that all RSA keys share the same set of numbers (“e”, “n”, “d”). My dad’s paper ”Why RSA Works” also gave me the grounding I needed to reason about and understand RSA cryptography.
Other inspirations include Zed Shaw’s vulnarb.com project, which was the first time I considered using TLS certificates for encrypting email. The Monkeysphere Project which inspired me to think of using the PGP web of trust for things other than email.
My work at Okta on key pinning introduced me to Python’s outstanding cryptographic library ”cryptography”. And most recently, my work on converting JWK formatted keys to PEM formatted keys proved how useful a command line utility for key conversion could be.
$ lokey --help $ lokey fetch $ lokey to
This release works, but only barely so. I’d like to know if other people find it useful and have ideas for what they’d want to use this tool for.
That said, I already know of many things that will need to be fixed or corrected soon:
- I don’t know if the keys generated by this tool will actually work in The Real World.
PGP and X.509 certificates in particular have a lot of options, I haven’t done any testing with software like Outlook, Mail.app, GPGTools (for Mac), iOS, etc. Please let me know what needs to be fixed here!
- I’d like lokey to be able to genereate X.509 keys that could be used for S/MIME and
SSL “client authentication” (where a browser authenticates with a web server).
I got a “proof of concept” working for this by turning lokey into a very simple “certificate authority”, this didn’t seem ideal though.
- I want to add support for all the various fingerprint formats in use.
- Passphrases for encrypted private keys shouldn’t be passed via a command line argument.
This could expose your passphrase!
- I need to release my tests for “Eris” the class I use to convert keys.
Before I do this, I need to make sure all the private keys are just test keys.
- Documentation. This should be a literate document.
- The text output for keys to match what you get with a tool like
pgpdump
oropenssl x509 -text
- Support the various key stores for Java, macOS, GPG, etc
- I want to support more key formats (Pu
- PuTTY
- SSH Certificates
- pkcs12?
- DKIM?
- I have no idea how people use key bundles, or how lokey should support them
See also, FIXME
notes in the source as well as my planned work in README.org
Cool! I got PGP to OpenSSH working!
How do I read a key? “Making openssl generate deterministic key” http://stackoverflow.com/q/22759465> You can’t, really
generate a certificate with openssl http://stackoverflow.com/a/10176685
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
$ gpg --gen-key gpg (GnuPG/MacGPG2) 2.0.30; Copyright (C) 2015 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 1y Key expires at Sun Feb 4 00:08:52 2018 PST Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Testing Key Email address: [email protected] Comment: Testing You selected this USER-ID: "Testing Key (Testing) <[email protected]>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O You need a Passphrase to protect your secret key. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 0E31BEDC marked as ultimately trusted public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: next trustdb check due at 2018-02-04 pub 2048R/0E31BEDC 2017-02-04 [expires: 2018-02-04] Key fingerprint = 809A 516D 890F E61E B4A5 CBA1 9DBF 138E 0E31 BEDC uid [ultimate] Testing Key (Testing) <[email protected]> sub 2048R/3A382837 2017-02-04 [expires: 2018-02-04]
https://github.com/mitchellrj/python-pgp
https://github.com/SecurityInnovation/PGPy
Looks like I’ll just need to create a PGPKey, then a UID, then add the UID to the key
http://pythonhosted.org/PGPy/examples.html#keys
echo -n | openssl s_client -connect google.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
It worked!!!
Look at this!
import pgpy
from pgpy.packet.fields import RSAPub,MPI
from pgpy.packet.packets import PubKeyV4
from pgpy.constants import PubKeyAlgorithm
def custRSAPub(n,e):
res = RSAPub()
res.n = MPI(n)
res.e = MPI(e)
return res
def custPubKeyV4(custkey):
res = PubKeyV4()
res.pkalg = PubKeyAlgorithm.RSAEncryptOrSign
res.keymaterial = custkey
res.update_hlen()
return res
def rsatogpg(e,N,name,**idargs):
"""
:param e,N: RSA parameters as Python integers or longints
:param name: Identity name
:param idargs: PGP Identity parameters, such as comment,email
:return: PGPy pubkey object
"""
rsakey = custPubKeyV4(custRSAPub(N,e))
pgpkey = pgpy.PGPKey()
pgpkey._key = rsakey
uid = pgpy.PGPUID.new(name, **idargs)
uid._parent = pgpkey
pgpkey._uids.append(uid)
return pgpkey
http://explo.yt/post/2016/05/20/Parsing-OpenSSH-RSA-keys-in-Python
Try to extract the public key from a private key
Looks like the core stuff is in fields(1099) - I might just need to extend this class myself.Made a trace file:python -m trace --trace app.py | tee trace.output.`date +%s`
Open that file in less
and then search for “app.py”
Next: Read each packet in PGP public key block and learn what each is. Study them, figure out how I should make one myself
pgpdump -ilmp pgpy-public-key.key
Things that I tried:
- Skimming more of the source code to see what I might be missing
- Looking for a “new()” method for the PubKey or PubKeyV4 classes
- Loading in a valid public key, but replacing “e” and “m”
Traceback (most recent call last): File "app.py", line 62, in <module> compression=[CompressionAlgorithm.ZLIB, CompressionAlgorithm.BZ2, CompressionAlgorithm.ZIP, CompressionAlgorithm.Uncompressed]) File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/pgp.py", line 1574, in add_uid uid |= self.certify(uid, SignatureType.Positive_Cert, **prefs) File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/decorators.py", line 125, in _action with self.usage(key, kwargs.get('user', None)) as _key: File "/Users/joel/brew/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__ return self.gen.next() File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/decorators.py", line 87, in usage em['keyid'] = key.fingerprint.keyid File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/pgp.py", line 1201, in fingerprint return self._key.fingerprint File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/packet/packets.py", line 794, in fingerprint plen = self.keymaterial.publen() File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/packet/fields.py", line 362, in publen return len(self) File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/packet/fields.py", line 352, in __len__ return sum(len(getattr(self, i)) for i in self.__pubfields__) File "/Users/joel/brew/lib/python2.7/site-packages/pgpy/packet/fields.py", line 352, in <genexpr> return sum(len(getattr(self, i)) for i in self.__pubfields__) TypeError: object of type 'long' has no len()
I got basic tests working. I also read the “man” page for “ssh-keygen”, things I learned:
- SSH has their own custom certificate format, looks cool
- You can control how moduli are tested by
ssh-keygen
(how many “rounds” of tests are done) - This tool might want to add support for SSH tests?
Spend time reading about other types of keys …
Found this: https://en.wikipedia.org/wiki/X.509#Major_protocols_and_standards_using_X.509_certificatesAccidently read more about Heartbleed
- Find a JWK library first
to_jwt()
is in the most recent version, not released yet!
mkdir upstream cd upstream/ git clone 'https://github.com/jpadilla/pyjwt.git' cd pyjwt/ python setup.py install
- “from_x”
- “to_x”
To convert:
- [X] openssh
- [X] jwk
- [X] pgp
- [X] x509 pem
eris = ErisPublicNumbers()
# Assume we've loaded the SSH key from somehwere
data = ssh_key
eris.read(data)
# This will print out info on SSH key we've just loaded
eris.info()
# This will write it as a JWK
eris.to.jwk()
class ErisPublicNumbers (RSAPublicNumbers):
def __init__(self):
'''
Base class for Eris Public Numbers
'''
# No command line tools to display this
self.pretty_print_cmd = False
self.name = "ErisPublicNumber"
self.
def serialize(self):
pass
def deserialize(self, data):
pass
def info(self):
# Print out the key in some nice format
if pretty_print_cmd:
# pipe output through the command!
pass
def __str__(self):
# Convert to string!
pass
def __repr__(self):
return "{name} ({fingerprint})".format(
name=self.name,
fingerprint=self.fingerprint())
def fingerprint(self):
pass
class JWT (ErisPublicNumbers):
'''
JWT (RFC 7519)
'''
def __init__(self):
self.pretty_print_cmd = ['jq']
def seralize(self):
pass
def deseralize(self, data):
pass
class X509 (ErisPublicNumbers):
'''
X.509 creator
'''
def __init__(self):
self.pretty_print_cmd = ['openssl', 'x509', '-text']
def seralize(self):
pass
def deseralize(self, data):
pass
class PGP (ErisPublicNumbers):
'''
PGP keys
'''
def __init__(self):
self.pretty_print_cmd = ['pgpdump']
def seralize(self):
pass
def deseralize(self, data):
pass
cmd --help cat key.jwk | lokey to openssh cat key.jwk | lokey to pgp --name="Joel Franusic" --email="[email protected]" lokey fetch jwk example.okta.com --kid=1b3c5 | lokey to openssh lokey fetch pgp [email protected] lokey fetch x509 joel.franusic.com lokey fetch github jpf lokey fetch keybase jfranusic
Going to take a look at HHGTP for a bit too
Awww yiss
I’ll use the name “Eris”Tell me what kind of key we got and print out “e” and “n” … trivial: https://github.com/ianchesal/keybase-python- Create requirements.txt
- Installing OpenSSL. I hate OpenSSL. https://twitter.com/jf/status/835936551439851521
- Turns out the issue wasn’t OpenSSL, it was outdated verions of
pip
andvirtualenv
on this system
Here are commands I’d like to be able to type
lokey fetch twitter jf lokey fetch facebook jfranusic lokey fetch coinbase jpf lokey fetch reddit joelfranusic lokey fetch hn jpf lokey fetch keybase jfranusic lokey fetch keybase --http=joel.franusic.com lokey fetch keybase --https=joel.franusic.com lokey fetch ssh chat.shazow.net lokey fetch ssl gliderlabs.com lokey fetch pgp '[email protected]' lokey fetch jwk example.okta.com lokey fetch github jpf
import paramiko
import pprint
class AllowAnythingPolicy(paramiko.MissingHostKeyPolicy):
def missing_host_key(self, client, hostname, key):
pprint.pprint(key.__dict__)
print key.public_numbers.e
print key.public_numbers.n
return
client = paramiko.SSHClient()
client.set_missing_host_key_policy(AllowAnythingPolicy())
client.connect('chat.shazow.net', username='lokey')
Search keyservers in order, until one is found:
lokey fetch pgp '[email protected]'
Search all keyservers
lokey fetch pgp '[email protected]' --all
Search one keyserver
lokey fetch pgp '[email protected]' --server=pgp.mit.edu
It would be nice to print out the list of keyservers somehow. Maybe I can use the docstring to store the list of servers?
I could use this, but I don’t think it’s what I want, I’d like people to be able to choose from other wacky (or private) keyservers: http://click.pocoo.org/6/options/#choice-options ?
from hkp import KeyServer
import pprint
# https://en.wikipedia.org/wiki/Key_server_(cryptographic)#Keyserver_examples
servers = ['keys.gnupg.net',
# 'subkeys.pgp.net',
'pgp.mit.edu',
'pool.sks-keyservers.net',
'zimmermann.mayfirst.org',
'keyserver.ubuntu.com']
for server in servers:
addr = 'http://{}'.format(server)
print 'Searching {}'.format(addr)
serv = KeyServer(addr)
rv = serv.search('[email protected]')
pprint.pprint(rv)
https://pypi.python.org/pypi/ssh-import-id/5.6
- Going to call it “pem”, this is what cryptography.io does (load_pem_public_key)
- Got it working!!
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgamsZfaSoeje3ychyFxv SnVvwLetawpY70HsTpa11m/KvTMChFuD3ApLyRxrTS/iWApTnVTVqP07a5jF49m0 N59CpdYvy/yUiJ0n0Q7obbT6KzL+np4yZqG9wvpqRDjJxo9QMB7C+Yg+/NHmmaNg QPr1gpkHRdWSlWnHyXDbo/oKO9JbSQoXIDzfgRcvh/orJ3txUWG4/Ah5GXyowFf0 eGPsEB823NlqP5ek1dUs4poWYeeuBz0UP32MIyGGb/Jln7dYBG/vjEdwgu1j9zwp eM5zHowMlaT2ssswwA6zIYh9ve9uzZK5i0utPtY3mPiWigoSjC5FMqkTEFI0iydt swIDAQAB -----END PUBLIC KEY-----http://stackoverflow.com/q/18039401 https://www.ietf.org/rfc/rfc4870.txt
Upload to GitHub too
Great tutorial! http://peterdowns.com/posts/first-time-with-pypi.html- Turn Keybase key into S/MIME certificate sounds like the first one?
- Give your keybase friend access to your SSH server
- Send an encrypted email to the owner of an HTTPS service
- Turn your friend’s keybase key into a GPG key for their email address
- Your keybase friend
- The owner of an HTTPS website
- The owner of an email domain secured with DKIM keys
- Your friend on GitHub
- Your keybase friend
- Your friend with a PGP key
- Your keybase friend
- Your friend on GitHub
- Someone in your PGP web of trust
It doesn’t look like there is a name for the output format below, should be easy to parse though!
- See “Example” below
- Surely there is a parser for this already?
cat test_keys/generated-x509 | openssl x509 -text
Certificate: Data: Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=CA, L=San Francisco, O=My Company, CN=mysite.com Validity Not Before: Aug 29 00:00:00 1997 GMT Not After : Sep 8 00:00:00 1997 GMT Subject: C=US, ST=CA, L=San Francisco, O=My Company, CN=mysite.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit) Modulus (1024 bit): 00:b4:fe:28:03:b7:7d:2d:94:ab:50:92:5f:5f:e5: 99:45:af:7b:b7:89:33:cd:b4:56:f4:d1:33:af:10: 75:46:48:08:6e:a6:01:7b:04:80:98:31:30:ff:f4: 53:41:39:71:6f:c4:99:8c:47:71:bd:2f:23:7c:91: 92:b8:10:94:7b:6c:b3:fa:78:0a:08:bc:15:e9:48: eb:45:9b:67:8b:97:a2:e3:1c:b2:b3:69:b7:87:63: 06:71:08:10:ab:4f:53:59:28:7a:44:47:58:c8:e4: 27:fc:17:20:41:d7:99:8c:c9:17:b3:86:59:15:27: cd:73:5d:1d:12:89:9c:77:4f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Alternative Name: DNS:localhost Signature Algorithm: sha256WithRSAEncryption 4b:db:38:11:c5:02:62:fb:04:59:e6:00:24:78:22:4e:e3:3e: 9a:47:41:b5:9b:84:9e:94:44:83:5b:a2:75:25:80:95:88:77: ca:d2:6a:23:af:fc:2d:cb:17:fc:05:74:5b:82:d7:89:86:20: 96:84:da:2d:3a:54:ae:a2:59:10:f8:cd:ed:7c:cd:fc:75:21: 52:07:a7:c2:6a:fb:da:9e:9b:e6:c2:69:0d:96:97:67:0a:a2: 55:80:6c:21:b6:95:76:48:8a:9a:f1:89:d9:70:0e:42:ca:cf: f7:b0:6a:53:1b:05:d3:9e:98:8c:fa:e7:95:78:7d:00:0c:f2: b8:00:85:e0:62:94:48:df:f1:c6:32:1f:a8:54:9d:bc:17:59: 05:a8:20:c4:87:d5:2e:5f:42:f6:9f:ce:dc:b0:91:34:70:89: 36:2c:ba:50:3f:62:47:6f:e7:68:5f:40:96:8c:fc:6a:36:eb: 31:94:2b:51:fc:ff:e3:a0:bd:cf:19:d0:88:65:7e:c2:36:2d: 88:bd:1d:c3:33:d5:ed:6b:bb:d7:ec:e1:8b:83:e7:33:13:21: a8:73:84:b4:a5:ee:ce:ba:69:82:5c:5b:7c:8a:69:9e:4b:98: 3f:56:99:93:be:61:52:b7:73:40:9f:44:56:9a:c8:0c:51:19: c2:c0:81:e4 -----BEGIN CERTIFICATE----- MIICxzCCAa+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJVUzEL MAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15 IENvbXBhbnkxEzARBgNVBAMMCm15c2l0ZS5jb20wHhcNOTcwODI5MDAwMDAwWhcN OTcwOTA4MDAwMDAwWjBcMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNV BAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoMCk15IENvbXBhbnkxEzARBgNVBAMM Cm15c2l0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALT+KAO3fS2U q1CSX1/lmUWve7eJM820VvTRM68QdUZICG6mAXsEgJgxMP/0U0E5cW/EmYxHcb0v I3yRkrgQlHtss/p4Cgi8FelI60WbZ4uXouMcsrNpt4djBnEIEKtPU1koekRHWMjk J/wXIEHXmYzJF7OGWRUnzXNdHRKJnHdPAgMBAAGjGDAWMBQGA1UdEQQNMAuCCWxv Y2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAS9s4EcUCYvsEWeYAJHgiTuM+mkdB tZuEnpREg1uidSWAlYh3ytJqI6/8LcsX/AV0W4LXiYYgloTaLTpUrqJZEPjN7XzN /HUhUgenwmr72p6b5sJpDZaXZwqiVYBsIbaVdkiKmvGJ2XAOQsrP97BqUxsF056Y jPrnlXh9AAzyuACF4GKUSN/xxjIfqFSdvBdZBaggxIfVLl9C9p/O3LCRNHCJNiy6 UD9iR2/naF9Aloz8ajbrMZQrUfz/46C9zxnQiGV+wjYtiL0dwzPV7Wu71+zhi4Pn MxMhqHOEtKXuzrppglxbfIppnkuYP1aZk75hUrdzQJ9EVprIDFEZwsCB5A== -----END CERTIFICATE-----
- Stub out features I want, but don’t have yet
lokey fetch keybase github:jpf lokey fetch keybase jfranusic
- timeout
- unable to reach server
- no key found on server
- no x509 CA cert
… Somehow PyJWT just didn’t want to work, so I changed to doing manual JWT decoding
- add examples
- for blank
lokey
command with examples
Lets look at what formats cryptography.io supports, looks like it supports:
- PEM
- DER
https://cryptography.io/en/latest/_modules/cryptography/hazmat/primitives/serialization/
Though they look the same (PEM formatted) private keys are different from PGP private keys However, SSH private keys seem to be the same as PEM private keys:OpenSSH key:
$ cat tests/fixtures/id_rsa | openssl rsa -text
X.509 key:
$ cat tests/fixtures/key-b-openssl-key.pem | openssl rsa -text
PGP key:
$ cat tests/fixtures/key-c-gpg-private.key | pgpdump
I can’t get the password protected version of this code working?
No clear way to force the IV here: https://github.com/pyca/cryptography/blob/3bab4e5e356409920e17e2a0aad1eec4f2135e6a/src/cryptography/hazmat/backends/openssl/backend.py#L1456-L1536 Here is how Cryptography tests this code: https://github.com/pyca/cryptography/blob/6012ccff0d709a80259f93a406eca5d133b40108/tests/hazmat/primitives/test_rsa.py#L2079-L2091
http://stackoverflow.com/questions/24093272/how-to-load-a-private-key-from-a-jwk-into-openssl https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-6.3.2
- Maybe I should just do this if you pipe somethign in without a flag?
- I added FIXME comments in code
- detect private keys
- properly handle unknown types
- print out input with error, or some of it?
- Relevant magic files: /usr/share/file/magic
- pgp
- gnu (GPG)
- ssh
- apple
(Keychain database files)
- gnome
(GNOME keyring)
- java
(Java KeyStore)
- securitycerts
- ssl
https://github.com/ahupp/python-magic https://github.com/h2non/filetype.py https://github.com/cdgriffith/puremagic
Next step:
- I think I’ll use libmagic wrapper until I can port one of the above … if it matters
- Will have:
- ErisPublic
- ErisPrivate
- Move load() to “Eris” namespace
- Use delegate pattern for “plugins”
SO EASY!
@cli.group()
@click.pass_context
def fetch(ctx):
"""Fetch key from place"""
pass
@fetch.command()
@click.pass_context
def keybase(ctx):
"""Fetch from keybase"""
print "KEYBASE"
- estimate effort to implement STDIN reader with “readback”
- I should just
read()
enough to peek, if good, thenread()
max bytes in and put into StringIO - nevermind … this was easy
python setup.py sdist upload -r pypitest python setup.py sdist upload -r pypiTruth Table:
STDIN | Subcommand | Expected Result |
---|---|---|
No | No | Help text printed with examples |
No | “fetch” | Key fetched |
No | “to” | Help text printed for “to” subcommand |
Yes | No | Key information printed |
Yes | “to” | Key converted |
Yes | “fetch” | Help text printed for “fetch” subcommand |
Simpler?
STDIN | Subcommand | Expected Result |
---|---|---|
No | No | Help text printed with examples |
No | Yes | Subcommand run |
Yes | No | Key information printed |
Yes | Yes | Subcommand run |
For variables in code:
interactive_terminal | subcommand | Expected Result |
---|---|---|
True | None | Help text printed with examples |
True | ”” | Subcommand run |
False | None | Key information printed |
False | ”” | Subcommand run |
Glider labs folks, Len, Jordan
https://web.archive.org/web/20110828210530/http://vulnarb.com/- [ ] RSA keypair
- [ ] CA keypair
- [ ] RSA HTTPS pair
- [ ] RSA S/MIME pair
- [ ] RSA HTTPS CSR
- [ ] HTTPS key for example.com
- [ ] HTTPS key for example.net
- [ ] HTTPS key for example.org
- [ ] HTTPS key for keybase.io
- [ ] HTTPS key for google.com
- [ ] HTTPS key for bing.com
- [ ] HTTPS key for duckduckgo.com
- [ ] GPG rsa keypair
- [ ] GPG ec keypair
- [ ] Public key from keybase
- [ ] rsa keypair
- [ ] dsa keypair
- [ ] ec keypair
- [ ] public key from GitHub
openssl smime -encrypt -des3 -in my-message.txt tests/fixtures/key-b-openssl-cert.pem > message-for-key-b
Decrypt with:
openssl smime -decrypt -in message-for-key-b -passin pass:12345678 -inkey tests/fixtures/key-b-openssl-key.pem
Lots of good stuff in this answer: https://security.stackexchange.com/a/45294
Here is the answer:
export GNUPGHOME=$(mktemp -d $HOME/.gnupgXXXXXX)
http://serverfault.com/a/528355
Here is how to script GPG: http://stackoverflow.com/a/23785134
Super frustrating, seems like GPG puts secret keys in some shared keystore, wtfhttps://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html--keyring file
Add file to the current list of keyrings.
If file begins with a tilde and a slash, these are replaced by the $HOME directory.
If the filename does not contain a slash, it is assumed to be in the GnuPG
home directory (“~/.gnupg” if –homedir or $GNUPGHOME is not used).
Note that this adds a keyring to the current list.
If the intent is to use the specified keyring alone, use --keyring
along with --no-default-keyring
.
If the the option --no-keyring
has been used no keyrings will be used at all.
“Here is the data I got, here is the command to view more”
- Got
- e
- n
- metadata
- To learn more:
- | openssl x509 -text
- | pgpdump
- print useful stuff in comment if we have it
- email if it’s in the PGP input
- email if its in the x509 input
- CN if email not in x509, etc
- x509 certs should have reasonable default for serial number
- unix time?
- x509 certs should have reasonable default for issuer and subject
See also:
- determine reasonable defaults for inputs
- estimate effort to implement “openssl-text” as output/input format
- find code in openssl that implements the
-text
flag
Findings:
- Looks like names are called “Long Names”, for example: https://github.com/openssl/openssl/blob/6f0ac0e2f27d9240516edb9a23b7863e7ad02898/include/openssl/objects.h#L634
- Here is what prints out “Certificate:” https://github.com/openssl/openssl/blob/c4a60150914fc260c3fc2854e13372c870bdde76/crypto/x509/t_x509.c#L66-L71 https://git.io/vD5s7
- It doesn’t look like there is a single bit of code that handles
-text
flag? Seems like each thing prints its own output. See below for X509, for exampleExample:
$ echo -n | openssl s_client -connect example.com:443 2> /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | openssl x509 -text Certificate: Data: Version: 3 (0x2) Serial Number: 0e:64:c5:fb:c2:36:ad:e1:4b:17:2a:eb:41:c7:8c:b0 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA Validity Not Before: Nov 3 00:00:00 2015 GMT Not After : Nov 28 12:00:00 2018 GMT Subject: C=US, ST=California, L=Los Angeles, O=Internet Corporation for Assigned Names and Numbers, OU=Technology, CN=www.example.org Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (2048 bit) Modulus (2048 bit): 00:b3:40:96:2f:61:63:3e:25:c1:97:ad:65:45:fb: ef:13:42:b3:2c:99:86:f4:b5:80:0b:76:dc:06:38: 2c:1f:a3:62:55:5a:36:76:de:ae:5d:fc:e2:e5:b4: e6:ec:5d:ca:ee:ca:df:50:16:24:2c:ee:fc:9a:b6: 8c:f6:a8:b3:ac:7a:08:7b:2a:1f:ad:5f:e7:fa:96: 59:25:ab:90:b0:f8:c2:3f:13:04:26:74:68:0f:c6: 78:2a:95:8a:5f:42:f2:0e:ed:52:a6:eb:68:23:89: e5:43:f8:6d:12:1b:62:42:7b:a8:05:f3:59:c4:5e: d6:c5:cc:46:c0:4b:19:b9:2d:4a:71:72:24:1e:5e: 55:44:93:ab:78:a1:47:4d:a5:dc:07:5a:9c:67:f4: 11:68:12:2f:d3:28:71:bc:ad:72:05:3c:16:75:d4: f8:72:58:ba:19:f1:dc:09:ed:f1:18:c6:92:2f:7d: bc:16:0b:37:8d:8a:ef:1b:6f:4f:b9:e0:7a:54:98: bf:b5:b6:cf:bb:aa:93:7f:0a:7f:1f:56:eb:a9:d8: e1:db:d5:39:d8:18:5b:d1:f2:64:33:d0:d6:c4:23: ff:09:ab:6d:71:ce:da:cf:c1:17:9c:23:be:2c:af: 2f:92:1c:3f:90:08:89:58:f2:b1:e1:10:6f:83:2e: f7:9f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Authority Key Identifier: keyid:51:68:FF:90:AF:02:07:75:3C:CC:D9:65:64:62:A2:12:B8:59:72:3B X509v3 Subject Key Identifier: A6:4F:60:1E:1F:2D:D1:E7:F1:23:A0:2A:95:16:E4:E8:9A:EA:6E:48 X509v3 Subject Alternative Name: DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 CRL Distribution Points: URI:http://crl3.digicert.com/sha2-ha-server-g4.crl URI:http://crl4.digicert.com/sha2-ha-server-g4.crl X509v3 Certificate Policies: Policy: 2.16.840.1.114412.1.1 CPS: https://www.digicert.com/CPS Policy: 2.23.140.1.2.2 Authority Information Access: OCSP - URI:http://ocsp.digicert.com CA Issuers - URI:http://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt X509v3 Basic Constraints: critical CA:FALSE Signature Algorithm: sha256WithRSAEncryption 84:a8:9a:11:a7:d8:bd:0b:26:7e:52:24:7b:b2:55:9d:ea:30: 89:51:08:87:6f:a9:ed:10:ea:5b:3e:0b:c7:2d:47:04:4e:dd: 45:37:c7:ca:bc:38:7f:b6:6a:1c:65:42:6a:73:74:2e:5a:97: 85:d0:cc:92:e2:2e:38:89:d9:0d:69:fa:1b:9b:f0:c1:62:32: 65:4f:3d:98:db:da:d6:66:da:2a:56:56:e3:11:33:ec:e0:a5: 15:4c:ea:75:49:f4:5d:ef:15:f5:12:1c:e6:f8:fc:9b:04:21: 4b:cf:63:e7:7c:fc:aa:dc:fa:43:d0:c0:bb:f2:89:ea:91:6d: cb:85:8e:6a:9f:c8:f9:94:bf:55:3d:42:82:38:4d:08:a4:a7: 0e:d3:65:4d:33:61:90:0d:3f:80:bf:82:3e:11:cb:8f:3f:ce: 79:94:69:1b:f2:da:4b:c8:97:b8:11:43:6d:6a:25:32:b9:b2: ea:22:62:86:0d:a3:72:7d:4f:ea:57:3c:65:3b:2f:27:73:fc: 7c:16:fb:0d:03:a4:0a:ed:01:ab:a4:23:c6:8d:5f:8a:21:15: 42:92:c0:34:a2:20:85:88:58:98:89:19:b1:1e:20:ed:13:20: 5c:04:55:64:ce:9d:b3:65:fd:f6:8f:5e:99:39:21:15:e2:71: aa:6a:88:82 -----BEGIN CERTIFICATE----- 5Oia6m5IMIGBBgNVHREEejB4gg93d3cuZXhhbXBsZS5vcmeCC2V4YW1wbGUuY29t ggtleGFtcGxlLmVkdYILZXhhbXBsZS5uZXSCC2V4YW1wbGUub3Jngg93d3cuZXhh bXBsZS5jb22CD3d3dy5leGFtcGxlLmVkdYIPd3d3LmV4YW1wbGUubmV0MA4GA1Ud DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0f BG4wbDA0oDKgMIYuaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2Vy dmVyLWc0LmNybDA0oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTIt aGEtc2VydmVyLWc0LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsG AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjCB gwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy dC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E aWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQC MAAwDQYJKoZIhvcNAQELBQADggEBAISomhGn2L0LJn5SJHuyVZ3qMIlRCIdvqe0Q 6ls+C8ctRwRO3UU3x8q8OH+2ahxlQmpzdC5al4XQzJLiLjiJ2Q1p+hub8MFiMmVP PZjb2tZm2ipWVuMRM+zgpRVM6nVJ9F3vFfUSHOb4/JsEIUvPY+d8/Krc+kPQwLvy ieqRbcuFjmqfyPmUv1U9QoI4TQikpw7TZU0zYZANP4C/gj4Ry48/znmUaRvy2kvI l7gRQ21qJTK5suoiYoYNo3J9T+pXPGU7Lydz/HwW+w0DpArtAaukI8aNX4ohFUKS wDSiIIWIWJiJGbEeIO0TIFwEVWTOnbNl/faPXpk5IRXicapqiII= -----END CERTIFICATE-----
Here is the code that prints out the above, apparently:
if (!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp, "Certificate:\n", 13) <= 0) goto err; if (BIO_write(bp, " Data:\n", 10) <= 0) goto err; } if (!(cflag & X509_FLAG_NO_VERSION)) { l = X509_get_version(x); if (l >= 0 && l <= 2) { if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0) goto err; } else { if (BIO_printf(bp, "%8sVersion: Unknown (%ld)\n", "", l) <= 0) goto err; } }
- See below for RSA sample:
$ cat test_keys/1024-key.pem | openssl rsa -text Enter pass phrase: Private-Key: (1024 bit) modulus: 00:cc:35:4e:a4:cc:9b:05:90:78:01:54:20:91:1c: c1:f7:ce:33:78:e0:e0:2d:9e:a3:78:9f:59:93:2a: b6:dd:a6:12:53:35:2f:a5:0e:54:63:20:d6:b9:23: 29:17:93:03:98:3c:88:7a:7a:4c:75:17:63:b1:32: 8b:da:a6:f7:a6:43:f7:09:af:cf:54:fa:25:20:c7: 15:da:45:c1:4e:5d:37:a7:9b:73:7a:ef:2e:9e:19: 3b:06:c5:ef:c5:0e:96:34:e3:3d:44:aa:37:29:f9: 21:0a:36:2b:0e:fc:14:87:bd:98:ba:5c:6e:1c:4d: 36:f2:bf:a7:7c:68:54:ae:13 publicExponent: 65537 (0x10001) privateExponent: 00:b2:4a:3c:7e:90:11:2d:1b:84:5b:0c:9b:5e:76: f0:37:2e:36:2c:6c:91:ed:e2:9a:b1:1e:d7:73:31: 10:f5:96:20:5b:bb:8c:fc:9b:f5:3b:93:19:46:0d: 17:bc:78:63:e4:0f:bd:cc:c9:68:65:b6:e5:18:79: 9c:37:6c:1d:bc:e1:a6:6e:b0:56:69:ab:7a:a4:11: 59:cb:16:e7:c9:b8:51:35:bd:fa:28:b8:db:12:62: bf:0a:8d:9d:78:6a:b7:4d:18:29:d0:31:a6:1e:3a: 09:d3:46:a7:55:7f:1a:e7:72:83:6d:84:22:30:be: 95:44:7c:c9:95:57:cf:3e:b9 prime1: 00:f2:04:26:cf:e9:05:35:35:74:aa:ff:42:cc:cf: 84:96:25:51:e7:b0:a8:66:db:75:26:ea:3f:8c:fc: 95:98:50:86:48:a5:75:ec:3d:6d:19:c9:7e:62:5e: c4:81:70:70:f3:29:82:ba:52:7e:5a:c3:bf:c0:43: a4:cf:32:f9:5f prime2: 00:d8:01:e8:95:a2:77:9d:94:c8:c4:16:c9:5d:21: 43:8e:56:2e:ec:c3:e3:78:9e:0f:09:c7:ab:83:05: a2:dd:50:a6:15:4e:ad:86:56:e7:dc:de:1b:20:ee: a3:30:36:ab:62:97:b2:c2:bf:4f:25:97:b9:95:dc: 4c:f4:75:23:cd exponent1: 2f:7e:4b:13:8f:f9:fa:a8:23:de:0e:bb:d0:2f:85: 28:65:e8:7d:dc:38:1f:ff:3f:2d:44:d8:f5:d4:f7: 92:6d:72:fc:bc:a3:b8:99:91:58:77:27:3b:2c:b7: c9:63:04:77:63:95:08:f5:79:60:5c:7b:bb:c2:4a: 8c:72:c7:67 exponent2: 79:91:79:68:dd:ab:1c:50:e4:3d:17:e5:f4:38:08: 61:4f:37:d1:a0:dd:a0:c0:b4:0d:f9:06:1a:13:4d: f9:e8:ad:d0:48:1b:79:03:e8:32:71:fe:2a:a6:a3: c9:3a:bb:72:1d:96:49:ec:89:8a:ca:bd:74:0e:2c: 71:58:8b:f1 coefficient: 70:63:99:39:b6:38:c6:97:72:fd:55:bf:c5:73:55: d8:35:47:eb:c2:58:ac:9f:90:b5:a2:60:65:11:de: 45:de:43:74:75:d0:18:22:94:19:4d:aa:f4:38:27: 1f:76:71:44:fe:b2:37:df:31:76:82:20:f0:ad:9e: f4:de:4c:ca writing RSA key -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQDMNU6kzJsFkHgBVCCRHMH3zjN44OAtnqN4n1mTKrbdphJTNS+l DlRjINa5IykXkwOYPIh6ekx1F2OxMovapvemQ/cJr89U+iUgxxXaRcFOXTenm3N6 7y6eGTsGxe/FDpY04z1Eqjcp+SEKNisO/BSHvZi6XG4cTTbyv6d8aFSuEwIDAQAB AoGBALJKPH6QES0bhFsMm1528DcuNixske3imrEe13MxEPWWIFu7jPyb9TuTGUYN F7x4Y+QPvczJaGW25Rh5nDdsHbzhpm6wVmmreqQRWcsW58m4UTW9+ii42xJivwqN nXhqt00YKdAxph46CdNGp1V/Gudyg22EIjC+lUR8yZVXzz65AkEA8gQmz+kFNTV0 qv9CzM+EliVR57CoZtt1Juo/jPyVmFCGSKV17D1tGcl+Yl7EgXBw8ymCulJ+WsO/ wEOkzzL5XwJBANgB6JWid52UyMQWyV0hQ45WLuzD43ieDwnHq4MFot1QphVOrYZW 59zeGyDuozA2q2KXssK/TyWXuZXcTPR1I80CQC9+SxOP+fqoI94Ou9AvhShl6H3c OB//Py1E2PXU95Jtcvy8o7iZkVh3Jzsst8ljBHdjlQj1eWBce7vCSoxyx2cCQHmR eWjdqxxQ5D0X5fQ4CGFPN9Gg3aDAtA35BhoTTfnordBIG3kD6DJx/iqmo8k6u3Id lknsiYrKvXQOLHFYi/ECQHBjmTm2OMaXcv1Vv8VzVdg1R+vCWKyfkLWiYGUR3kXe Q3R10BgilBlNqvQ4Jx92cUT+sjffMXaCIPCtnvTeTMo= -----END RSA PRIVATE KEY-----
Code used to print the above: https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_ameth.c#L309-L359
static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv) { const RSA *x = pkey->pkey.rsa; char *str; const char *s; int ret = 0, mod_len = 0; if (x->n != NULL) mod_len = BN_num_bits(x->n); if (!BIO_indent(bp, off, 128)) goto err; if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ? "RSA-PSS" : "RSA") <= 0) goto err; if (priv && x->d) { if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0) goto err; str = "modulus:"; s = "publicExponent:"; } else { if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0) goto err; str = "Modulus:"; s = "Exponent:"; } if (!ASN1_bn_print(bp, str, x->n, NULL, off)) goto err; if (!ASN1_bn_print(bp, s, x->e, NULL, off)) goto err; if (priv) { if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off)) goto err; if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off)) goto err; if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off)) goto err; if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off)) goto err; if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off)) goto err; if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off)) goto err; } if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off)) goto err; ret = 1; err: return ret; }
- Looks like these are all the signatures of the openssl functions used to print out stuff
$ find openssl -type f -iname '*.c' | xargs egrep '.*int.*_print\(BIO' openssl/apps/x509.c:static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); openssl/apps/x509.c:static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) openssl/crypto/asn1/a_gentm.c:int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) openssl/crypto/asn1/a_print.c:int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) openssl/crypto/asn1/a_time.c:int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm) openssl/crypto/asn1/a_utctm.c:int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) openssl/crypto/asn1/t_bitst.c:int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, openssl/crypto/asn1/t_pkey.c:int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int indent) openssl/crypto/asn1/t_pkey.c:int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, openssl/crypto/asn1/t_spki.c:int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) openssl/crypto/asn1/tasn_prn.c:static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, openssl/crypto/asn1/tasn_prn.c:int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, openssl/crypto/asn1/tasn_prn.c:static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, openssl/crypto/asn1/x_bignum.c:static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, openssl/crypto/asn1/x_bignum.c:static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, openssl/crypto/asn1/x_long.c:static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, openssl/crypto/asn1/x_long.c:static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, openssl/crypto/bn/bn_print.c:int BN_print(BIO *bp, const BIGNUM *a) openssl/crypto/dh/dh_ameth.c:static int do_dh_print(BIO *bp, const DH *x, int indent, int ptype) openssl/crypto/dh/dh_ameth.c:static int dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dh/dh_ameth.c:static int dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dh/dh_ameth.c:static int dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dh/dh_ameth.c:int DHparams_print(BIO *bp, const DH *x) openssl/crypto/dsa/dsa_ameth.c:static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) openssl/crypto/dsa/dsa_ameth.c:static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dsa/dsa_ameth.c:static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dsa/dsa_ameth.c:static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/dsa/dsa_ameth.c:static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, openssl/crypto/dsa/dsa_prn.c:int DSA_print(BIO *bp, const DSA *x, int off) openssl/crypto/dsa/dsa_prn.c:int DSAparams_print(BIO *bp, const DSA *x) openssl/crypto/ec/ec_ameth.c:static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype) openssl/crypto/ec/ec_ameth.c:static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ec/ec_ameth.c:static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ec/ec_ameth.c:static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ec/ec_ameth.c:int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) openssl/crypto/ec/ec_ameth.c:int ECParameters_print(BIO *bp, const EC_KEY *x) openssl/crypto/ec/eck_prn.c:int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) openssl/crypto/ec/ecx_meth.c:static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ec/ecx_meth.c:static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ec/ecx_meth.c:static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/ocsp/ocsp_prn.c:static int ocsp_certid_print(BIO *bp, OCSP_CERTID *a, int indent) openssl/crypto/ocsp/ocsp_prn.c:int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *o, unsigned long flags) openssl/crypto/ocsp/ocsp_prn.c:int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags) openssl/crypto/rsa/rsa_ameth.c:static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss, openssl/crypto/rsa/rsa_ameth.c:static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv) openssl/crypto/rsa/rsa_ameth.c:static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/rsa/rsa_ameth.c:static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, openssl/crypto/rsa/rsa_ameth.c:static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, openssl/crypto/rsa/rsa_prn.c:int RSA_print(BIO *bp, const RSA *x, int off) openssl/crypto/ts/ts_rsp_print.c:static int ts_status_map_print(BIO *bio, const struct status_map_st *a, openssl/crypto/ts/ts_rsp_print.c:static int ts_status_map_print(BIO *bio, const struct status_map_st *a, openssl/crypto/x509/t_crl.c:int X509_CRL_print(BIO *out, X509_CRL *x) openssl/crypto/x509/t_req.c:int X509_REQ_print(BIO *bp, X509_REQ *x) openssl/crypto/x509/t_x509.c:int X509_print(BIO *bp, X509 *x) openssl/crypto/x509/t_x509.c:int X509_ocspid_print(BIO *bp, X509 *x) openssl/crypto/x509/t_x509.c:int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, openssl/crypto/x509/t_x509.c:int X509_aux_print(BIO *out, X509 *x, int indent) openssl/crypto/x509/x_name.c:static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, openssl/crypto/x509/x_name.c:static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, openssl/crypto/x509/x_name.c:int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase) openssl/crypto/x509v3/v3_alt.c:int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) openssl/crypto/x509v3/v3_prn.c:static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, openssl/crypto/x509v3/v3_prn.c:int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, openssl/crypto/x509v3/v3_prn.c:int X509V3_extensions_print(BIO *bp, const char *title, openssl/crypto/x509v3/v3_prn.c:static int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, openssl/ssl/ssl_txt.c:int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
- So, I think it’s safe to say that there isn’t some set “Standard”, I’m just going to adopt what I like and just make sure I can match the X509 “standard”
OpenSSH Public Key (vX): --or-- Certificate: Data: RSA Public Key: (2048 bit) Modulus (2048 bit): 00:a8:6b:74:9f:22:e8:52:53:49:8e:ac:2d:0e:2c: cb:78:3d:32:6b:54:71:5b:8e:59:3e:ae:69:f2:ed: bd:1a:44:56:5e:a3:9b:34:d4:38:1c:35:84:8c:a4: 6d:33:19:d6:3b:96:1b:50:ab:b9:56:ff:a1:b4:06: 5d:9b:83:68:43:b4:36:8b:c2:25:97:39:b3:05:58: 95:0a:8c:49:55:2c:f0:09:8f:1e:1b:c3:5a:64:c2: 38:7a:88:38:bd:50:14:94:3d:2c:7a:86:18:38:da: d2:e8:d0:ed:88:db:27:ad:a9:62:28:65:68:f3:d8: 5a:e2:18:89:70:3e:c9:14:84:39:fa:ff:c4:9e:7c: ad:3d:5c:ba:5f:59:10:86:8a:2d:75:bd:60:57:30: 9a:cd:7e:5a:d1:a4:70:1f:e0:05:d8:fd:a8:7a:e2: 47:cb:3c:90:c8:33:78:56:96:45:0c:8e:76:1d:68: 73:15:62:c4:29:1b:fa:c9:0c:14:e1:48:16:b6:71: 16:58:ab:08:53:cb:4f:c9:a1:30:b6:06:c2:d8:5b: 99:25:15:3c:36:64:70:33:8c:93:1e:58:12:a9:8d: 3c:a8:6c:1b:ca:06:9f:9a:b8:1a:06:b3:ae:ea:5a: 97:06:d5:78:b5:98:5b:2c:e8:01:cf:f4:3d:76:13: 96:f1 Exponent: 65537 (0x10001) Comment: joel@charon
pgpdump
https://github.com/openssl/openssl/tree/master/test
- JWK arrays
- PEM packages
- GPG keys with sub-keys, etc
- This is just SSH format, with text record wrapping
- Might add a DNS interface for import though! That would be rad.