# Notice
This repository is not actively maintained, as this was only intended as a POC for the complete library [scheiblingco/sshkey-tools](https://github.com/scheiblingco/sshkey-tools). Leaving it archived here since it gives an easier/better understanding of the inner workings of the protocol.CERTKEYS certificates.
Any code in this repository should be thoroughly tested before implementing any of it close to any production context.
# OpenSSH Certificate Parser
A python-based OpenSSH certificate parser. Based on the gist by [@corny](https://gist.github.com/corny/8264b74a130eb663dbf3d3f0fe0e0ec9)
# Limitations
- DSA parsing is currently broken, will be fixed in a future release
- Signature, signature key, public key and nonce parsing has not been implemented yet
## Installation
### From PyPi
```bash
python3 -m pip install ssh_cert_parser
```
### From source
```bash
git clone https://github.com/scheibling/ssh-cert-parser.git
cd ssh-cert-parser
python3 setup.py install
```
## Usage
### CLI
```bash
# Output to stdout as test
ssh_cert_parser.py -f /path/to/ssh/certificate
# Result:
# nonce: 8Å+c♥©¡%|ÜÂ××~♂♥íÖ°À `Ø↔¬$z
# curve: nistp256
# public_key: ♦à²÷xÒd¤r♠Ðc½§$íw▲RrwVOê∟Mç↑í»±Ãa»£¡cD↑fôæF?ê☺ëØâ↨Òþ
# serial: 123
# type: 1
# key id: ecdsa_256_ecdsa_256_serial
# valid principals:
# principal_1
# principal_2
# principal_3
# valid after: 1644245220
# valid before: 1644331703
# critical options:
# extensions:
# permit-X11-forwarding
# permit-agent-forwarding
# permit-port-forwarding
# permit-pty
# permit-user-rc
# reserved:
# signature key:
# ecdsa-sha2-nistp256
# nistp256
# ♦ M0ËݵWFÝO♣5ySUw☻h▬4Õbû>üÞ♣½#>í¹þL´
# Ý*%5O!ÒhLÀgómMþûË
# signature:
# ecdsa-sha2-nistp256
# !¹"ºlÕ(ÄÐÐ♀↓º¤▲Klܤ}¡6vÙ ☺é04×P¥
# ↑→zujÇú« õ%[ïl¬öuhR°♂
# Output to stdout as json
ssh_cert_parser.py -f /path/to/ssh/certificate --json
# Result:
# {
# "nonce": "8\u00c5+c\u0003\u00a9\u00a1%\u008e|\u00dc\u0086\u00c2\u00d7\u00d7~\u000b\u0003\u00ed\u00d6\u0099\u0081\u00b0\u00c0\t`\u00d8\u001d\u00ac\u009a$z",
# "curve": "nistp256",
# "public_key": "\u0004\u00e0\u00b2\u009a\u00f7x\u00d2d\u00a4r\u0006\u00d0\u0087\u0004\bc\u0097\u009a\u00bd\u00a7$\u0097\u00edw\u001eRrwVO\u0091\u00ea\u001c\u009e?z\u00caM\u00e7\u0018\u00ed\u00bb\u00b1\u00c3a\u00bb\u00a3\u00a1cD\u0018f\u00f4\u00e6F?\u00ea\u0001\u0087\u00eb\u00d8\u00e2\u0017\u00d2\u00fe",
# "serial": 123,
# "type": 1,
# "key id": "ecdsa_256_ecdsa_256_serial",
# "valid principals": [
# "principal_1",
# "principal_2",
# "principal_3"
# ],
# "valid after": 1644245220,
# "valid before": 1644331703,
# "critical options": "",
# "extensions": [
# "permit-X11-forwarding",
# "permit-agent-forwarding",
# "permit-port-forwarding",
# "permit-pty",
# "permit-user-rc"
# ],
# "reserved": "",
# "signature key": [
# "ecdsa-sha2-nistp256",
# "nistp256",
# "\u0004\u00a0M0\u00cb\u00dd\u00b5WF\u00ddO\u00055ySUw\u0002h\u00164\u008a\u00d5b\u00fb>\u00fc\u00de\u0005\u00bd#\u009e\u00c2>\u00ed\u00b9\u00feL\u00b4\u009f4\u00ef\u0085\u00dd*%5O!\u00d2h\u0099\u0090\u0083L\u00c0g\u00f3mM\u00fe\u00fb\u00cb\u009f\u00b7"
# ],
# "signature": [
# "ecdsa-sha2-nistp256",
# "\u0000\u0000\u0000!\u0000\u00b9\u008c\"\u00ba\u0007l\u00d5(\u00c4\u00d0\u00d0\f\u0019\u00ba\u00a4\u001eK\u0097l\u009en8&\u00e2\u00dc\u00a4}\u00a16\u008ev\u00d9\u0000\u0000\u0000 \u0001\u00e904\u00d7P\u00a5\u0084\u0018\u001azuj\u00c7\u00fa\u00ab\u00a0\u00f5%[\u00efl\u0096\u00ac\u00f6\u0099uhR\u00b0\u0091\u000b"
# ]
# }
# Output to file as json
ssh_cert_parser.py -f /path/to/ssh/certificate --output /path/to/output/file.json
# Overwrite existing file if exists
ssh_cert_parser.py -f /path/to/ssh/certificate --output /path/to/output/file.json --overwrite
```
### In scripts
```python
from ssh_cert_parser.core import parse_from_string, parse_from_file, parse_from_bytes
cert_1 = parse_from_file('/path/to/ssh/certificate')
cert_2 = parse_from_string('ecdsa-sha2-nistp521-cert-v01@openssh.com AAAAA....')
cert_3 = parse_from_bytes('ecdsa-sha2-nistp521-cert-v01', b'AAAAA....')
# To print the readable contents of a certificate
print(cert_1)
# To convert to string
str_cert2 = str(cert_1)
# To get a dict
dict_cert3 = cert_1.to_dict()
```
Raw data
{
"_id": null,
"home_page": "https://github.com/scheibling/ssh-cert-parser",
"name": "ssh-cert-parser",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": "",
"keywords": "python openssh ssh-certificate certificate parser decoder",
"author": "Lars Scheibling",
"author_email": "lars@scheibling.se",
"download_url": "https://files.pythonhosted.org/packages/08/b5/d093c4bcd7bc23520587ad185b01bf923b0274b4428ecb409cdb28bc510e/ssh-cert-parser-0.1.post3817469255.tar.gz",
"platform": null,
"description": "# Notice\nThis repository is not actively maintained, as this was only intended as a POC for the complete library [scheiblingco/sshkey-tools](https://github.com/scheiblingco/sshkey-tools). Leaving it archived here since it gives an easier/better understanding of the inner workings of the protocol.CERTKEYS certificates. \n\nAny code in this repository should be thoroughly tested before implementing any of it close to any production context.\n\n# OpenSSH Certificate Parser\nA python-based OpenSSH certificate parser. Based on the gist by [@corny](https://gist.github.com/corny/8264b74a130eb663dbf3d3f0fe0e0ec9)\n\n# Limitations\n- DSA parsing is currently broken, will be fixed in a future release\n- Signature, signature key, public key and nonce parsing has not been implemented yet\n\n## Installation\n### From PyPi\n```bash\npython3 -m pip install ssh_cert_parser\n```\n\n### From source\n```bash\ngit clone https://github.com/scheibling/ssh-cert-parser.git\ncd ssh-cert-parser\npython3 setup.py install\n```\n\n## Usage\n### CLI\n```bash\n# Output to stdout as test\nssh_cert_parser.py -f /path/to/ssh/certificate\n\n# Result:\n# nonce: 8\u00c5+c\u2665\u00a9\u00a1%|\u00dc\u00c2\u00d7\u00d7~\u2642\u2665\u00ed\u00d6\u00b0\u00c0 `\u00d8\u2194\u00ac$z\n# curve: nistp256\n# public_key: \u2666\u00e0\u00b2\u00f7x\u00d2d\u00a4r\u2660\u00d0c\u00bd\u00a7$\u00edw\u25b2RrwVO\u00ea\u221fM\u00e7\u2191\u00ed\u00bb\u00b1\u00c3a\u00bb\u00a3\u00a1cD\u2191f\u00f4\u00e6F?\u00ea\u263a\u00eb\u00d8\u00e2\u21a8\u00d2\u00fe\n# serial: 123\n# type: 1\n# key id: ecdsa_256_ecdsa_256_serial\n# valid principals:\n# principal_1\n# principal_2\n# principal_3\n# valid after: 1644245220\n# valid before: 1644331703\n# critical options:\n# extensions:\n# permit-X11-forwarding\n# permit-agent-forwarding\n# permit-port-forwarding\n# permit-pty\n# permit-user-rc\n# reserved:\n# signature key:\n# ecdsa-sha2-nistp256\n# nistp256\n# \u2666 M0\u00cb\u00dd\u00b5WF\u00ddO\u26635ySUw\u263bh\u25ac4\u00d5b\u00fb>\u00fc\u00de\u2663\u00bd#>\u00ed\u00b9\u00feL\u00b4\n# \u00dd*%5O!\u00d2hL\u00c0g\u00f3mM\u00fe\u00fb\u00cb\n# signature:\n# ecdsa-sha2-nistp256\n# !\u00b9\"\u00bal\u00d5(\u00c4\u00d0\u00d0\u2640\u2193\u00ba\u00a4\u25b2Kl\u00dc\u00a4}\u00a16v\u00d9 \u263a\u00e904\u00d7P\u00a5\n# \u2191\u2192zuj\u00c7\u00fa\u00ab \u00f5%[\u00efl\u00ac\u00f6uhR\u00b0\u2642\n\n# Output to stdout as json\nssh_cert_parser.py -f /path/to/ssh/certificate --json\n\n# Result:\n# {\n# \"nonce\": \"8\\u00c5+c\\u0003\\u00a9\\u00a1%\\u008e|\\u00dc\\u0086\\u00c2\\u00d7\\u00d7~\\u000b\\u0003\\u00ed\\u00d6\\u0099\\u0081\\u00b0\\u00c0\\t`\\u00d8\\u001d\\u00ac\\u009a$z\",\n# \"curve\": \"nistp256\",\n# \"public_key\": \"\\u0004\\u00e0\\u00b2\\u009a\\u00f7x\\u00d2d\\u00a4r\\u0006\\u00d0\\u0087\\u0004\\bc\\u0097\\u009a\\u00bd\\u00a7$\\u0097\\u00edw\\u001eRrwVO\\u0091\\u00ea\\u001c\\u009e?z\\u00caM\\u00e7\\u0018\\u00ed\\u00bb\\u00b1\\u00c3a\\u00bb\\u00a3\\u00a1cD\\u0018f\\u00f4\\u00e6F?\\u00ea\\u0001\\u0087\\u00eb\\u00d8\\u00e2\\u0017\\u00d2\\u00fe\",\n# \"serial\": 123,\n# \"type\": 1,\n# \"key id\": \"ecdsa_256_ecdsa_256_serial\",\n# \"valid principals\": [\n# \"principal_1\",\n# \"principal_2\",\n# \"principal_3\"\n# ],\n# \"valid after\": 1644245220,\n# \"valid before\": 1644331703,\n# \"critical options\": \"\",\n# \"extensions\": [\n# \"permit-X11-forwarding\",\n# \"permit-agent-forwarding\",\n# \"permit-port-forwarding\",\n# \"permit-pty\",\n# \"permit-user-rc\"\n# ],\n# \"reserved\": \"\",\n# \"signature key\": [\n# \"ecdsa-sha2-nistp256\",\n# \"nistp256\",\n# \"\\u0004\\u00a0M0\\u00cb\\u00dd\\u00b5WF\\u00ddO\\u00055ySUw\\u0002h\\u00164\\u008a\\u00d5b\\u00fb>\\u00fc\\u00de\\u0005\\u00bd#\\u009e\\u00c2>\\u00ed\\u00b9\\u00feL\\u00b4\\u009f4\\u00ef\\u0085\\u00dd*%5O!\\u00d2h\\u0099\\u0090\\u0083L\\u00c0g\\u00f3mM\\u00fe\\u00fb\\u00cb\\u009f\\u00b7\"\n# ],\n# \"signature\": [\n# \"ecdsa-sha2-nistp256\",\n# \"\\u0000\\u0000\\u0000!\\u0000\\u00b9\\u008c\\\"\\u00ba\\u0007l\\u00d5(\\u00c4\\u00d0\\u00d0\\f\\u0019\\u00ba\\u00a4\\u001eK\\u0097l\\u009en8&\\u00e2\\u00dc\\u00a4}\\u00a16\\u008ev\\u00d9\\u0000\\u0000\\u0000 \\u0001\\u00e904\\u00d7P\\u00a5\\u0084\\u0018\\u001azuj\\u00c7\\u00fa\\u00ab\\u00a0\\u00f5%[\\u00efl\\u0096\\u00ac\\u00f6\\u0099uhR\\u00b0\\u0091\\u000b\"\n# ]\n# }\n\n# Output to file as json\nssh_cert_parser.py -f /path/to/ssh/certificate --output /path/to/output/file.json\n\n# Overwrite existing file if exists\nssh_cert_parser.py -f /path/to/ssh/certificate --output /path/to/output/file.json --overwrite\n\n```\n\n### In scripts\n```python\nfrom ssh_cert_parser.core import parse_from_string, parse_from_file, parse_from_bytes\n\ncert_1 = parse_from_file('/path/to/ssh/certificate')\n\ncert_2 = parse_from_string('ecdsa-sha2-nistp521-cert-v01@openssh.com AAAAA....')\n\ncert_3 = parse_from_bytes('ecdsa-sha2-nistp521-cert-v01', b'AAAAA....')\n\n# To print the readable contents of a certificate\nprint(cert_1)\n\n# To convert to string\nstr_cert2 = str(cert_1)\n\n# To get a dict\ndict_cert3 = cert_1.to_dict()\n\n```\n",
"bugtrack_url": null,
"license": "GnuPG 3.0",
"summary": "A python module for parsing OpenSSH certificates",
"version": "0.1.post3817469255",
"split_keywords": [
"python",
"openssh",
"ssh-certificate",
"certificate",
"parser",
"decoder"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "a554423fb7655d49bdf9fd4d7f53044a",
"sha256": "0c1cb37683efa566c7e4ca76fabe9b5bf4ed5b892129b22b653d2be747a747df"
},
"downloads": -1,
"filename": "ssh_cert_parser-0.1.post3817469255-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a554423fb7655d49bdf9fd4d7f53044a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 19803,
"upload_time": "2023-01-01T15:14:30",
"upload_time_iso_8601": "2023-01-01T15:14:30.562689Z",
"url": "https://files.pythonhosted.org/packages/38/d6/7d02600689f4bae8f4a806bdf7b0ce715f59f822893a3a5735d04f06a834/ssh_cert_parser-0.1.post3817469255-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "905fe9c7cab64e8e239786afeb0ea054",
"sha256": "e93bff42914b6d716b51fdc8b4017dca784bd41a2cd6c57f7fac9a5854a375aa"
},
"downloads": -1,
"filename": "ssh-cert-parser-0.1.post3817469255.tar.gz",
"has_sig": false,
"md5_digest": "905fe9c7cab64e8e239786afeb0ea054",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 20411,
"upload_time": "2023-01-01T15:14:31",
"upload_time_iso_8601": "2023-01-01T15:14:31.949162Z",
"url": "https://files.pythonhosted.org/packages/08/b5/d093c4bcd7bc23520587ad185b01bf923b0274b4428ecb409cdb28bc510e/ssh-cert-parser-0.1.post3817469255.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-01-01 15:14:31",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "scheibling",
"github_project": "ssh-cert-parser",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "click",
"specs": []
}
],
"lcname": "ssh-cert-parser"
}