# step 5 display the code to user to enter on OnlyKey # This method prevents some malware on a users system from sending fake requests to be signed # at the same time as real requests and tricking the user into signing the wrong data print( 'Please enter the 3 digit challenge code on OnlyKey (and press ENTER if necessary)' ) print('{} {} {}'.format(b1, b2, b3)) raw_input() shared_secret1 = alice.get_ecdh_key(bob.get_pubkey()) shared_secret2 = bob.get_ecdh_key(alice.get_pubkey()) print('Trying to read the shared secret from OnlyKey...') ok_shared_secret = '' while ok_shared_secret == '': time.sleep(0.5) ok_shared_secret = ok.read_bytes(len(shared_secret1), to_bytes=True) print('OnlyKey Shared Secret =', hexlify(ok_shared_secret)) print('Local Shared Secret1 =', hexlify(shared_secret1)) print() print('Local Shared Secret2 =', hexlify(shared_secret2)) print() print('Assert that both shared secrets match') print((hexlify(alice.get_ecdh_key(bob.get_pubkey())))) assert repr(shared_secret1) == repr(ok_shared_secret) print('Ok, secrets match') print()
# if signature key = type + 64 # if decryption key = type + 32 # if authentication key = type + 16 # For this example it will be a decryption key time.sleep(1.5) print ok.read_string() time.sleep(2) print 'You should see your OnlyKey blink 3 times' print print 'Trying to read the public RSA N part 1...' ok.send_message(msg=Message.OKGETPUBKEY, payload=chr(1)) #, payload=[1, 1]) time.sleep(1.5) for _ in xrange(10): ok_pubkey1 = ok.read_bytes(64, to_str=True, timeout_ms=1000) if len(ok_pubkey1) == 64: break time.sleep(1) print print 'received=', repr(ok_pubkey1) print 'Trying to read the public RSA N part 2...' for _ in xrange(10): ok_pubkey2 = ok.read_bytes(64, to_str=True, timeout_ms=1000) if len(ok_pubkey2) == 64: break time.sleep(1)
class Client(object): """Client wrapper for SSH authentication device.""" def __init__(self, curve=formats.CURVE_NIST256): """Connect to hardware device.""" self.device_name = 'OnlyKey' self.ok = OnlyKey() self.curve = curve def __enter__(self): """Start a session, and test connection.""" self.ok.read_string(timeout_ms=50) empty = 'a' while not empty: empty = self.ok.read_string(timeout_ms=50) return self def __exit__(self, *args): """Forget PIN, shutdown screen and disconnect.""" log.info('disconnected from %s', self.device_name) self.ok.close() def get_identity(self, label, index=0): """Parse label string into Identity protobuf.""" identity = string_to_identity(label) identity['proto'] = 'ssh' identity['index'] = index print 'identity', identity return identity def get_public_key(self, label): log.info('getting public key from %s...', self.device_name) log.info('Trying to read the public key...') # Compute the challenge pin h = hashlib.sha256() h.update(label) data = h.hexdigest() if self.curve == formats.CURVE_NIST256: data = '02' + data else: data = '01' + data data = data.decode("hex") log.info('Identity hash =%s', repr(data)) self.ok.send_message(msg=Message.OKGETPUBKEY, slot_id=132, payload=data) time.sleep(.5) for _ in xrange(2): ok_pubkey = self.ok.read_bytes(64, to_str=True, timeout_ms=10) if len(ok_pubkey) == 64: break log.info('received= %s', repr(ok_pubkey)) if len(set(ok_pubkey[34:63])) == 1: ok_pubkey = ok_pubkey[0:32] log.info('Received Public Key generated by OnlyKey= %s', repr(ok_pubkey)) vk = ed25519.VerifyingKey(ok_pubkey) return formats.export_public_key(vk=vk, label=label) else: ok_pubkey = ok_pubkey[0:64] log.info('Received Public Key generated by OnlyKey= %s', repr(ok_pubkey)) vk = ecdsa.VerifyingKey.from_string(ok_pubkey, curve=ecdsa.NIST256p) return formats.export_public_key(vk=vk, label=label) def sign_ssh_challenge(self, label, blob): """Sign given blob using a private key, specified by the label.""" msg = _parse_ssh_blob(blob) log.debug('%s: user %r via %r (%r)', msg['conn'], msg['user'], msg['auth'], msg['key_type']) log.debug('nonce: %s', binascii.hexlify(msg['nonce'])) log.debug('fingerprint: %s', msg['public_key']['fingerprint']) log.debug('hidden challenge size: %d bytes', len(blob)) # self.ok.send_large_message(payload=blob, msg=Message.OKSIGNSSHCHALLENGE) log.info('please confirm user "%s" login to "%s" using %s', msg['user'], label, self.device_name) h1 = hashlib.sha256() h1.update(label) data = h1.hexdigest() data = data.decode("hex") test_payload = blob + data # Compute the challenge pin h2 = hashlib.sha256() h2.update(test_payload) d = h2.digest() assert len(d) == 32 def get_button(byte): ibyte = ord(byte) return ibyte % 6 + 1 b1, b2, b3 = get_button(d[0]), get_button(d[15]), get_button(d[31]) log.info('blob to send', repr(test_payload)) # Determine type of key to derive on OnlyKey for signature # 201 = ed25519 # 202 = P256 # 203 = secp256k1 keytype = msg['key_type'] if msg['key_type'].startswith('ssh-ed25519'): this_slot_id = 201 log.info('Key type ed25519') elif msg['key_type'].startswith('ecdsa-sha2-nistp256'): this_slot_id = 202 log.info('Key type P256') else: this_slot_id = 203 log.info('Key type secp256k1') self.ok.send_large_message2(msg=Message.OKSIGNCHALLENGE, payload=test_payload, slot_id=this_slot_id) #TODO ping messages so that we don't need enter key to tell when done. print 'Please confirm user', msg[ 'user'], 'login to', label, 'using', self.device_name print( 'Enter the 3 digit challenge code shown below on OnlyKey to authenticate' ) print '{} {} {}'.format(b1, b2, b3) raw_input() for _ in xrange(10): result = self.ok.read_bytes(64, to_str=True, timeout_ms=200) if len(result) >= 60: log.info('received= %s', repr(result)) while len(result) < 64: result.append(0) log.info('disconnected from %s', self.device_name) self.ok.close() return result raise Exception('failed to sign challenge')
print 'Setting SSH private...' ok.set_ecc_key(101, (1 + 64), privkey.to_seed()) # ok.set_ecc_privsend_message(msg=Message.OKSETPRIV, payload=privkey.to_seed()) time.sleep(1.5) print ok.read_string() time.sleep(2) print 'You should see your OnlyKey blink 3 times' print print 'Trying to read the pubkey...' ok.send_message(msg=Message.OKGETPUBKEY, payload=chr(101)) #, payload=[1, 1]) time.sleep(1.5) for _ in xrange(10): ok_pubkey = ok.read_bytes(32, to_str=True) if len(ok_pubkey) == 32: break time.sleep(1) print print 'received=', repr(ok_pubkey) if not ok_pubkey: raise Exception('failed to set the SSH key') print 'Assert that the received pubkey match the one generated locally' assert ok_pubkey == pubkey.to_bytes() print 'Ok, pubkey matches' print
# Challenge_button3 = Challenge_button3 + '0' + 1; # } # step 5 display the code to user to enter on OnlyKey # This method prevents some malware on a users system from sending fake requests to be signed # at the same time as real requests and tricking the user into signing the wrong data print( 'Please enter the 3 digit challenge code on OnlyKey (and press ENTER if necessary)' ) print('{} {} {}'.format(b1, b2, b3)) input() print('Trying to read the shared secret from OnlyKey...') ok_shared_secret = '' while ok_shared_secret == '': time.sleep(0.5) ok_shared_secret = ok.read_bytes(64, to_str=True) print('OnlyKey Shared Secret =', repr(ok_shared_secret)) print('Local Shared Secret =', repr(ok_shared_secret)) print() print('Assert that both shared secrets match') assert repr(shared_secret) == repr(ok_shared_secret) print('Ok, secrets match') print() #print 'Trying to read the KEK from OnlyKey...' #ok_KEK = '' #while ok_KEK == '': # time.sleep(0.5) # ok_KEK = ok.read_bytes(len(KEK), to_str=True)
# if signature key = type + 64 # if decryption key = type + 32 # if authentication key = type + 16 # For this example it will be a decryption key time.sleep(1.5) print(ok.read_string()) time.sleep(2) print('You should see your OnlyKey blink 3 times') print() print('Trying to read the public RSA N part 1...') ok.send_message(msg=Message.OKGETPUBKEY, payload=chr(1)) #, payload=[1, 1]) time.sleep(1.5) for _ in xrange(10): ok_pubkey1 = ok.read_bytes(64, to_str=True) if len(ok_pubkey1) == 64: break time.sleep(1) print() print('received=', repr(ok_pubkey1)) print('Trying to read the public RSA N part 2...') for _ in xrange(10): ok_pubkey2 = ok.read_bytes(64, to_str=True) if len(ok_pubkey2) == 64: break time.sleep(1)