Releases: obelisk/sshcerts
Bumping Ring + Others
Bug Fixes and PRs
This release has a lot of updates to make the code more stable and handle more issues with malformed keys and certificates.
It also has a PR from @1Dragoon to make parsing better and add more serialization features.
FIDO and SK Support
Finally after lots of work, sshcerts
has merged support for not only reading SK style public and private keys, but signing certificates with them as well!
This can be tested out with the new example programs using sign-with-file
(sign-with-yubikey
is for PIV signing functionality). The library supports both Ecdsa and Ed25519 keys and can also verify attestations using the new fido-lite
feature. By default it will try to sign with the first FIDO HID device it can find, and with no pin. Both of these can be set manually in a private key of SK type to override this allowing you to use custom pins or specified devices.
The test suite has been expanded to attempt to cover all these new use cases and a few new examples to how how they can be integrated. For a more complex example, the Rustica project (https://github.com/obelisk/rustica) uses this new code to support remote registration and attestation of SSH hardware keys and provides SSH certificates (generated by this library) for them.
Minor Fixes from Clippy
Ran clippy across the codebase and fixed all the found issues. No breaking changes so just a point release.
More Versatile Signing Support
API Changes
Breaking Changes to Certificate::sign(&self, _)
This is a breaking change for people who use the Certificate::sign
function with something other than the provided PrivateKey
type. This is because before, the function (or closure) passed in was responsible for formatting the signature in SSH format. This created weird logical dependencies where SSH specific parsing code could not be easily isolated. Now that formatting happens automatically in the sign call (or technically the function I'm about to explain next)
New Public API Function Certificate::add_signature(&self, _)
This is a new API function available in the Certificate
struct allowing you to add a signature directly to the Certificate
instead of passing a closure which handles the signing for you. This was added because when working on Rustica, I found it was impossible to have a signature provided by an external service due to the closure needing to be async
. The solution to this problem I adopted was to add the new Certificate::tbs_certificate
which gives the raw data buffer that needs to be signed to create a valid certificate. When a signature is passed into Certificate::add_signature
, the function will correctly format the signature for SSH then check if adding that signature would result in a valid certificate. If the certificate is valid, it returns Ok(self)
after adding the signature and filling the serialized member. If the certificate is invalid, an error is returned.
New Public API Function Certificate::tbs_certificate(&self)
This is pretty simple function that simply returns a Vec<u8>
containing all the bytes of a correctly formatted SSH certificate but without the signature. A signature over the hash of this data passed to Certificate::add_signature
will result in a correct and fully signed SSH certificate.
Other Changes
- Tests added for
rsa-signing
because it turns out there were no tests that could catch failures in the RSA signing system - Tests added for creating a certificate, serializing it, then parsing it again. This is to catch any errors introduced in further changes to the serialization system (as reading and writing certificates are separate but complimentary code paths).
- Removed the log dependency when using the
yubikey-support
feature. Over the past months I kept removing logs because the error system got better and in this release I removed the final one. - New API function
x509::der_encoding_to_ssh_public_key
. It parses a DER encoded ECDSA public key and returns the crate'sPublicKey
type. I would like to make this parsing more versatile in the future, to support at least RSA and hopefully Ed25519 as well.
Clone impl on Extensions and CriticalOptions
This was missing and I needed in Rustica, so I've added it and cut a point release.
x509 Module
Pulls the x509 parsing code out of the Yubikey module into its own module. This new module is gated by the feature x509-support
so as to not increase dependencies for people who just need basic SSH certificate/key support.
Maintenance of Dependencies
SSHCerts has been using a quite outdated yubikey dependency and this updates it a version that is modern and receiving updates.
It also restructures the yubikey module to be more sane and allow better isolation if different yubikey modes can be supported in the future (like FIDO).
Encrypted Private Key Support
SSHCerts can now handle reading encrypted private keys encrypted with AES256-CTR + bcrypt (the current default). The API for reading private keys has remained the same so no updates should be required but there are now sister functions *_with_passphrase
which will attempt decryption.
Calling a *_with_passphrase(2)
will not fail if the key is unencrypted, the decryption routine will just not run.
Since supported encrypted keys required adding new dependencies and I'm trying to keep this as light as possible, encrypted key support is gated behind the option feature encrypted-keys
.
Unlike rsa-signing
, this is not a default feature.
Other Updates
- There have also been a couple documentation updates
- Key validation is more strict. It extracts the public key from the private key ensuring it matches the stated public key in the key file.
- Abstraction around reading a private key in byte format. This is the same format ssh-agents use so you can now turn those into usable private keys.
RSA Certificate Bug Fix
Fixes a bug that made certificates for RSA public keys unusable.
Thanks @WanzenBug for finding and contributing the fix!