Skip to content
This repository has been archived by the owner on Dec 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #6 from github/cert-transport-ext
Browse files Browse the repository at this point in the history
Add U2F transport-hint extension to attestation cert
  • Loading branch information
mastahyeti authored Jul 27, 2017
2 parents 65f5d89 + c540240 commit 85ab67e
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 19 deletions.
75 changes: 56 additions & 19 deletions SelfSignedCertificate/SelfSignedCertificate.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,65 @@
"\x74\xe6\xc2\xda\x23\x93\xff\xac\x1d\x50\x34\x6c\x5c\x23\x90\x65"
"\x57\x93\x3e\xcb\x93\xff\x6e\xde\xd1";

/*
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: ecdsa-with-SHA256
Issuer: CN=Soft U2F, O=GitHub Inc., OU=Security
Validity
Not Before: Jul 26 20:09:08 2017 GMT
Not After : Jul 24 20:09:08 2027 GMT
Subject: CN=Soft U2F, O=GitHub Inc., OU=Security
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:f6:9c:ab:24:14:4b:b4:ef:87:f7:0f:23:1c:5c:
d4:f5:78:04:ac:f8:e0:c6:b2:b3:e3:52:18:3d:80:
39:1f:6b:d2:79:d2:6a:4c:83:64:74:e6:c2:da:23:
93:ff:ac:1d:50:34:6c:5c:23:90:65:57:93:3e:cb:
93:ff:6e:de:d1
ASN1 OID: prime256v1
X509v3 extensions:
1.3.6.1.4.1.45724.2.1.1:
....
Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:fe:22:1d:97:b8:ea:ea:12:bb:9f:42:14:85:
0f:48:17:65:b5:e0:95:93:5e:a1:a3:d6:6d:0f:b1:6f:39:f7:
22:02:20:64:d7:dc:2f:5c:6c:38:2a:f7:65:f5:78:6a:39:b0:
b1:4a:97:45:28:ef:7d:df:21:02:15:1b:88:4a:d4:41:7a
*/
const unsigned char *cert = (unsigned char*)
"\x30\x82\x01\x15\x30\x81\xbd\xa0\x03\x02\x01\x02\x02\x01\x01\x30"
"\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x15\x31\x13\x30"
"\x11\x06\x03\x55\x04\x03\x0c\x0a\x6d\x61\x73\x74\x61\x68\x79\x65"
"\x74\x69\x30\x1e\x17\x0d\x31\x37\x30\x36\x30\x39\x31\x34\x30\x38"
"\x31\x37\x5a\x17\x0d\x31\x37\x30\x36\x31\x30\x31\x34\x30\x38\x31"
"\x37\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0c\x0a\x6d"
"\x61\x73\x74\x61\x68\x79\x65\x74\x69\x30\x59\x30\x13\x06\x07\x2a"
"\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07"
"\x03\x42\x00\x04\xf6\x9c\xab\x24\x14\x4b\xb4\xef\x87\xf7\x0f\x23"
"\x1c\x5c\xd4\xf5\x78\x04\xac\xf8\xe0\xc6\xb2\xb3\xe3\x52\x18\x3d"
"\x80\x39\x1f\x6b\xd2\x79\xd2\x6a\x4c\x83\x64\x74\xe6\xc2\xda\x23"
"\x93\xff\xac\x1d\x50\x34\x6c\x5c\x23\x90\x65\x57\x93\x3e\xcb\x93"
"\xff\x6e\xde\xd1\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02"
"\x03\x47\x00\x30\x44\x02\x20\x7c\xa5\x9b\x1e\x3a\x0e\xc4\xe1\xff"
"\x67\x76\xd3\xde\x93\xbc\x11\x02\xef\xbb\x1b\x18\x52\x32\x03\x07"
"\xf0\xea\xb1\xfa\x36\x70\x33\x02\x20\x3f\x92\xec\x0c\xbe\xc6\xd5"
"\xe8\x57\x92\x43\xe4\x3e\x4a\xdd\xd4\xd0\x8c\x7b\x6c\x02\x6c\xfd"
"\x1e\x8f\x84\x34\x2f\xdf\x81\xe1\x36";
"\x30\x82\x01\x7e\x30\x82\x01\x24\xa0\x03\x02\x01\x02\x02\x01\x01"
"\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x3c\x31\x11"
"\x30\x0f\x06\x03\x55\x04\x03\x0c\x08\x53\x6f\x66\x74\x20\x55\x32"
"\x46\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x47\x69\x74\x48"
"\x75\x62\x20\x49\x6e\x63\x2e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b"
"\x0c\x08\x53\x65\x63\x75\x72\x69\x74\x79\x30\x1e\x17\x0d\x31\x37"
"\x30\x37\x32\x36\x32\x30\x30\x39\x30\x38\x5a\x17\x0d\x32\x37\x30"
"\x37\x32\x34\x32\x30\x30\x39\x30\x38\x5a\x30\x3c\x31\x11\x30\x0f"
"\x06\x03\x55\x04\x03\x0c\x08\x53\x6f\x66\x74\x20\x55\x32\x46\x31"
"\x14\x30\x12\x06\x03\x55\x04\x0a\x0c\x0b\x47\x69\x74\x48\x75\x62"
"\x20\x49\x6e\x63\x2e\x31\x11\x30\x0f\x06\x03\x55\x04\x0b\x0c\x08"
"\x53\x65\x63\x75\x72\x69\x74\x79\x30\x59\x30\x13\x06\x07\x2a\x86"
"\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03"
"\x42\x00\x04\xf6\x9c\xab\x24\x14\x4b\xb4\xef\x87\xf7\x0f\x23\x1c"
"\x5c\xd4\xf5\x78\x04\xac\xf8\xe0\xc6\xb2\xb3\xe3\x52\x18\x3d\x80"
"\x39\x1f\x6b\xd2\x79\xd2\x6a\x4c\x83\x64\x74\xe6\xc2\xda\x23\x93"
"\xff\xac\x1d\x50\x34\x6c\x5c\x23\x90\x65\x57\x93\x3e\xcb\x93\xff"
"\x6e\xde\xd1\xa3\x17\x30\x15\x30\x13\x06\x0b\x2b\x06\x01\x04\x01"
"\x82\xe5\x1c\x02\x01\x01\x04\x04\x03\x02\x03\x08\x30\x0a\x06\x08"
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00\x30\x45\x02\x21\x00"
"\xfe\x22\x1d\x97\xb8\xea\xea\x12\xbb\x9f\x42\x14\x85\x0f\x48\x17"
"\x65\xb5\xe0\x95\x93\x5e\xa1\xa3\xd6\x6d\x0f\xb1\x6f\x39\xf7\x22"
"\x02\x20\x64\xd7\xdc\x2f\x5c\x6c\x38\x2a\xf7\x65\xf5\x78\x6a\x39"
"\xb0\xb1\x4a\x97\x45\x28\xef\x7d\xdf\x21\x02\x15\x1b\x88\x4a\xd4"
"\x41\x7a";

const int priv_len = 121;
const int cert_len = 281;
const int cert_len = 386;

@implementation SelfSignedCertificate {}

Expand Down
3 changes: 3 additions & 0 deletions script/generate_certificate
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

ruby script/generate_certificate.rb
77 changes: 77 additions & 0 deletions script/generate_certificate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/ruby

require "openssl"

PRIV = OpenSSL::PKey::EC.new(
"\x30\x77\x02\x01\x01\x04\x20\x03\x84\x2a\xc7\xf4\xcd\xe3\x67\xde"\
"\xa0\x56\xc6\x4f\x7f\x3b\x15\xea\x7d\x4b\xc4\x83\xca\xc6\x97\x9f"\
"\x2a\x31\x93\xad\x57\x31\x09\xa0\x0a\x06\x08\x2a\x86\x48\xce\x3d"\
"\x03\x01\x07\xa1\x44\x03\x42\x00\x04\xf6\x9c\xab\x24\x14\x4b\xb4"\
"\xef\x87\xf7\x0f\x23\x1c\x5c\xd4\xf5\x78\x04\xac\xf8\xe0\xc6\xb2"\
"\xb3\xe3\x52\x18\x3d\x80\x39\x1f\x6b\xd2\x79\xd2\x6a\x4c\x83\x64"\
"\x74\xe6\xc2\xda\x23\x93\xff\xac\x1d\x50\x34\x6c\x5c\x23\x90\x65"\
"\x57\x93\x3e\xcb\x93\xff\x6e\xde\xd1"
)

# From "FIDO U2F Authenticator Transports Extension" spec.
# X509 Extension OID for specifying supported transports.
U2F_TRANSPORT_EXTENSION_OID = "1.3.6.1.4.1.45724.2.1.1"

# From "FIDO U2F Authenticator Transports Extension" spec.
# BIT STRING values for U2F_TRANSPORT_EXTENSION_OID.
U2F_TRANSPORT_BLUETOOTH_RADIO = 0b10000000
U2F_TRANSPORT_BLUETOOTH_LOW_ENERGY_RADIO = 0b01000000
U2F_TRANSPORT_USB = 0b00100000
U2F_TRANSPORT_NFC = 0b00010000
U2F_TRANSPORT_USB_INTERNAL = 0b00001000

SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
DAY = 24 * HOUR
YEAR = 365 * DAY

def bit_string_extension(oid, value)
bsvalue = OpenSSL::ASN1::BitString.new([value].pack("C*"))

# There's probably a "smart" way to do this.
bsvalue.unused_bits = value.to_s(2).match(/(0*)$/)[1].size

OpenSSL::X509::Extension.new(oid, bsvalue, false)
end

def generate_cert(private_key:, subject:, transports:)
# https://bugs.ruby-lang.org/issues/8177
private_key.define_singleton_method(:private?) { private_key? }
private_key.define_singleton_method(:public?) { public_key? }

OpenSSL::X509::Certificate.new().tap do |cert|
cert.version = 2
cert.serial = 1
cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
cert.not_before = Time.now
cert.not_after = Time.now + (10 * YEAR)
cert.public_key = private_key

cert.add_extension(bit_string_extension(
U2F_TRANSPORT_EXTENSION_OID,
transports
))

cert.sign(private_key, OpenSSL::Digest::SHA256.new)
end
end

cert = generate_cert(
private_key: PRIV,
subject: "CN=Soft U2F/O=GitHub Inc./OU=Security",
transports: U2F_TRANSPORT_USB_INTERNAL,
).to_der

puts "Cert size: #{cert.bytesize}"

puts "Cert: "
cert.bytes.each_slice(16) do |bytes|
line = bytes.map { |b| "\\x%02x" % b }.join
puts %Q["#{line}"]
end

0 comments on commit 85ab67e

Please sign in to comment.