Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] SSH Data Signatures #44

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
47745ab
Ensure comment is always empty string on export
May 30, 2023
20e987b
Restored functionality to choose RSA hash algorithm
May 30, 2023
ab8783a
Added Rsa alg choice to documentation
May 30, 2023
4f33133
Linting
May 30, 2023
cb0f262
Lock cryptography requirement to <41
scheibling Jun 3, 2023
b0448b0
Removed DSA tests from unit tests
Jun 7, 2023
dfef738
Removed DSA Support
Jun 7, 2023
81708b3
Fixed validation for string values for the datetime fields
Jun 7, 2023
bcd27b2
Fixed misspelling of timestamp
Jun 7, 2023
c985e54
Added "always" option to datetime fields
Jun 7, 2023
212e0ba
Pinned dependency versions
scheibling Oct 3, 2023
874134d
Linting, switched back to pylint_report
scheibling Oct 3, 2023
acd9bfc
Added pylint
scheibling Oct 3, 2023
a5e3425
Fixed pylint_report command in CI
scheibling Oct 3, 2023
644cff9
Added logo, badges to readme
scheibling Oct 3, 2023
6febe54
Fixed badge for build
scheibling Oct 3, 2023
1c6e86c
Bump black from 23.9.1 to 23.10.0
dependabot[bot] Oct 23, 2023
d50eace
Bump faker from 19.6.2 to 19.11.0
dependabot[bot] Oct 23, 2023
6a2a975
Bump pylint from 3.0.0 to 3.0.2
dependabot[bot] Oct 23, 2023
43a89c0
Bump black from 23.10.0 to 23.10.1
dependabot[bot] Oct 30, 2023
9176e10
Bump faker from 19.11.0 to 19.13.0
dependabot[bot] Nov 6, 2023
d4a6bbd
Finished signature decoder
scheibling Nov 6, 2023
fc2d5dc
Signature validation for file now working
scheibling Nov 10, 2023
6101b0f
Signing and validation now works
scheibling Dec 31, 2023
5dc620e
Saving signatures now works
scheibling Jan 1, 2024
e0477ba
Removed data parameter from to_string/to_file
scheibling Jan 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"customizations": {
"vscode": {
"extensions": [
"scheiblingco.code-pypack",
"scheiblingco.code-cmd-repeat"
]
}
}
}
1 change: 1 addition & 0 deletions .github/workflows/deploy_testing.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
name: "Release Tests"
on:
release:
types: [created]
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/dev_testing.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
name: "Development Tests"
on:
push:
paths-ignore:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
name: "Pylint"
on:
push:
paths-ignore:
Expand All @@ -23,12 +24,11 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pylint pylint-report pylint-json2html
pip install -r requirements-test.txt

- name: Run tests
run: |
pylint src/sshkey_tools | tee | pylint-json2html -o report.html
python3 -m pylint src/sshkey_tools | tee | pylint_report -o report.html

- name: Upload report
uses: actions/upload-artifact@v1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
name: "Build Release"
on:
release:
types: [published]
Expand Down
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,13 @@ report.html
test_certificate
testing.py
.idea
core
core
/id_rsa
/id_rsa.pub
/id_ecdsa*
/id_dsa*
/id_ed25519*
hello.txt
hello.txt.sig

/testkeys
6 changes: 5 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
[MASTER]
load-plugins=pylint_report
extension-pkg-allow-list=cryptography.hazmat.bindings._rust

[REPORTS]
output-format=json
output-format=pylint_report.CustomJsonReporter
25 changes: 25 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
click = ">=7.1"
cryptography = ">=41.0"
bcrypt = ">=4.0"
enum34 = ">=1.1"
prettytable = ">=3.1"
pytimeparse2 = ">=1.4"

[dev-packages]
pylint-report = "*"
paramiko = "*"
coverage = "*"
black = "*"
pytest-cov = "*"
faker = "*"
cprint = "*"
pylint = "*"

[requires]
python_version = "3.9"
768 changes: 768 additions & 0 deletions Pipfile.lock

Large diffs are not rendered by default.

54 changes: 45 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
![SSHKey Tools](./assets/sshkey-tools-plain.svg)
# sshkey-tools
[![PyPI version](https://badge.fury.io/py/sshkey-tools.svg)](https://badge.fury.io/py/sshkey-tools)
![Linting](https://github.com/scheiblingco/sshkey-tools/actions/workflows/linting.yml/badge.svg)
![Testing-Dev](https://github.com/scheiblingco/sshkey-tools/actions/workflows/dev_testing.yml/badge.svg)
![Testing-Build](https://github.com/scheiblingco/sshkey-tools/actions/workflows/deploy_testing.yml/badge.svg)
![Build](https://github.com/scheiblingco/sshkey-tools/actions/workflows/publish.yml/badge.svg)
[![CodeQL](https://github.com/scheiblingco/sshkey-tools/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/scheiblingco/sshkey-tools/actions/workflows/github-code-scanning/codeql)



Python package for managing OpenSSH keypairs and certificates ([protocol.CERTKEYS](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys)). Supported functionality includes:

## Notice
The DSA algorithm has been deprecated and is removed in pyca/cryptography 41.x, meaning **version 0.9.* of this package will be the last to support DSA keys and certificates** for SSH. If there is any demand to reintroduce DSA support, please open an issue regarding this and we'll look into it.

For now, **0.9.* will be restricted to version <41.1 of the cryptography package** and **0.10 will have its DSA support removed**. We've introduced a deprecation notice in version 0.9.3.

### Background
The DSA algorithm is considered deprecated and will be removed in a future version. If possible, use RSA, [(ECDSA)](https://billatnapier.medium.com/ecdsa-weakness-where-nonces-are-reused-2be63856a01a) or ED25519 as a first-hand choice.

### Notice from OpenSSH:
```
OpenSSH 7.0 and greater similarly disable the ssh-dss (DSA) public key algorithm. It too is weak and we recommend against its use. It can be re-enabled using the HostKeyAlgorithms configuration option: sshd_config(5) HostKeyAlgorithms
```

[ECDSA has some flaws](https://billatnapier.medium.com/ecdsa-weakness-where-nonces-are-reused-2be63856a01a), especially when using short nonces or re-using nonces, it can still be used but exercise some caution in regards to nonces/re-signing identical data multiple times.

# Features
### SSH Keys
- Supports RSA, DSA, ECDSA and ED25519 keys
- Supports RSA, ECDSA and ED25519 keys
- Import existing keys from file, string, byte data or [pyca/cryptography](https://github.com/pyca/cryptography) class
- Generate new keys
- Get public key from private keys
Expand All @@ -13,7 +37,7 @@ Python package for managing OpenSSH keypairs and certificates ([protocol.CERTKEY
- Generate fingerprint

### OpenSSH Certificates
- Supports RSA, DSA, ECDSA and ED25519 certificates
- Supports RSA, ECDSA and ED25519 certificates
- Import existing certificates from file, string or bytes
- Verify certificate signature against internal or separate public key
- Create new certificates from CA private key and subject public key
Expand All @@ -22,11 +46,7 @@ Python package for managing OpenSSH keypairs and certificates ([protocol.CERTKEY
- Export certificates to file, string or bytes

# Roadmap
- [x] Rewrite certificate field functionality for simpler usage
- [ ] Re-add functionality for changing RSA hash method
- [ ] Add CLI functionality
- [ ] Convert to/from putty format (keys only)

See issues for planned features and fixes

# Installation

Expand All @@ -49,12 +69,18 @@ pip3 install ./
# Documentation
You can find the full documentation at [scheiblingco.github.io/sshkey-tools/](https://scheiblingco.github.io/sshkey-tools/)

## Building the documentation
```bash
pdoc3 src/sshkey_tools/ -o docs --html
cp -rf docs/sshkey_tools/* docs/
rm -rf docs/sshkey_tools
```

## SSH Keypairs (generating, loading, exporting)
```python
# Import the certificate classes
from sshkey_tools.keys import (
RsaPrivateKey,
DsaPrivateKey,
EcdsaPrivateKey,
Ed25519PrivateKey,
EcdsaCurves
Expand All @@ -69,7 +95,8 @@ rsa_priv = RsaPrivateKey.generate()
rsa_priv = RsaPrivateKey.generate(2048)

# Generate DSA keys (since SSH only supports 1024-bit keys, this is the default)
dsa_priv = DsaPrivateKey.generate()
# DEPRECATED
# dsa_priv = DsaPrivateKey.generate()

# Generate ECDSA keys (The default curve is P521)
ecdsa_priv = EcdsaPrivateKey.generate()
Expand Down Expand Up @@ -124,6 +151,7 @@ b"\0xc\0a\........"
The loaded private key objects can be used to sign bytestrings, and the public keys can be used to verify signatures on those
```python
from sshkey_tools.keys import RsaPrivateKey, RsaPublicKey
from sshkey_tools.fields import RsaAlgs

signable_data = b'This is a message that will be signed'

Expand All @@ -133,6 +161,10 @@ pubkey = RsaPrivateKey.public_key
# Sign the data
signature = privkey.sign(signable_data)

# When using an RSA key for the signature, you can specify the hashing algorithm
# The default algorithm is SHA512
signature = privkey.sign(signable_data, RsaAlgs.SHA512)

# Verify the signature (Throws exception if invalid)
pubkey.verify(signable_data, signature)
```
Expand Down Expand Up @@ -308,6 +340,10 @@ certificate.sign()
```

## Changelog
### 0.9.1
- Updated documentation
- Fix for bug where exception would occur when trying to export a key without a comment set

### 0.9
- Adjustments to certificate field handling for easier usage/syntax autocompletion
- Updated testing
Expand Down
93 changes: 93 additions & 0 deletions assets/sshkey-tools-plain.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions dev.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM mcr.microsoft.com/devcontainers/universal:2

RUN curl https://pyenv.run | bash \
&& echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc \
&& echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc \
&& echo 'eval "$(pyenv init -)"' >> ~/.bashrc

Loading
Loading