Skip to content

Instantly share code, notes, and snippets.

@dainnilsson
Created April 14, 2021 08:22
Show Gist options
  • Save dainnilsson/6deedb990cbc9af535a63dab0506c146 to your computer and use it in GitHub Desktop.
Save dainnilsson/6deedb990cbc9af535a63dab0506c146 to your computer and use it in GitHub Desktop.
ykman - custom certificate
from ykman.device import connect_to_device
from ykman.piv import sign_certificate_builder
from yubikit.core.smartcard import SmartCardConnection
from yubikit.piv import PivSession, MANAGEMENT_KEY_TYPE, SLOT, KEY_TYPE
from cryptography import x509
from cryptography.x509.oid import NameOID
import datetime
"""
This script will connect to a YubiKey and generate a self-signed certificate in slot 9C (SIGNATURE).
The CertificateBuilder class from cryptography.io can be used to customize the certificate more, see:
https://cryptography.io/en/latest/x509/reference/#x-509-certificate-builder
This script requires ykman 4.0.0 or later installed as a Python module.
Example (using Bash):
$ virtualenv ykman-script
$ cp certificate.py ykman-script/
$ cd ykman-script
$ . ./bin/activate
(ykman-script) $ pip install yubikey-manager
(ykman-script) $ python certificate.py
"""
# Connect to any YubiKey with a CCID interface
with connect_to_device(connection_types=[SmartCardConnection])[0] as connection:
# Establish a session with the PIV application
piv = PivSession(connection)
# Authenticate with the management key
piv.authenticate(
MANAGEMENT_KEY_TYPE.TDES,
bytes.fromhex("010203040506070801020304050607080102030405060708"),
)
# Generate a new key pair
public_key = piv.generate_key(SLOT.SIGNATURE, KEY_TYPE.ECCP256)
# Create a certificate
now = datetime.datetime.utcnow()
valid_to = now + datetime.timedelta(days=365)
subject = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "example")])
builder = (
x509.CertificateBuilder() # This can be customized much more...
.public_key(public_key)
.subject_name(subject)
.issuer_name(subject) # Same as subject on self-signed certificate.
.serial_number(x509.random_serial_number())
.not_valid_before(now)
.not_valid_after(valid_to)
)
# Sign the certificate using the key on the YubiKey.
piv.verify_pin("123456")
certificate = sign_certificate_builder(
piv, SLOT.SIGNATURE, KEY_TYPE.ECCP256, builder
)
# Load the certificate into the slot
piv.put_certificate(SLOT.SIGNATURE, certificate)
print("Done")
@dainnilsson
Copy link
Author

dainnilsson commented Apr 14, 2021

To instead create a CSR, use https://cryptography.io/en/latest/x509/reference/#x-509-csr-certificate-signing-request-builder-object and

from ykman.piv import sign_csr_builder

csr = sign_csr_builder(piv, SLOT.SIGNATURE, public_key, builder)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment