Skip to content

Commit 63d4782

Browse files
committed
1.2.1
1 parent 8fd010f commit 63d4782

3 files changed

Lines changed: 51 additions & 68 deletions

File tree

onlykey/cli.py

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,48 +51,8 @@ def prompt_pin():
5151
return
5252

5353
if len(sys.argv) > 1:
54-
if sys.argv[1] == 'ecc':
55-
# ECC subcommands
5654

57-
# Create a new private key
58-
if sys.argv[2] == 'new':
59-
signing_key, _ = nacl.signing.SigningKey.generate()
60-
61-
with open('ecc_private.key', 'wb+') as f:
62-
f.write(signing_key.encode(encoder=nacl.encoding.HexEncoder))
63-
64-
print('ECC private key written to ecc_private.key')
65-
66-
# Load a private key to the OnlyKey
67-
elif sys.argv[2] == 'load':
68-
69-
privkey = 'ecc_private.key'
70-
if len(privkey) == 4:
71-
privkey = sys.argv[3]
72-
73-
if not os.path.exists(privkey):
74-
print('{} does not exists'.format(privkey))
75-
76-
with open(privkey, 'rb') as f:
77-
raw_privkey = f.read()
78-
print ()
79-
print ('Enter ECC key slot number to use (1 - 32) or enter 0 to list key labels')
80-
print ()
81-
slot = int(input())
82-
83-
while slot == 0:
84-
ok.displaykeylabels()
85-
print ()
86-
print ('Enter ECC key slot number to use (1 - 32) or enter 0 to list key labels')
87-
print ()
88-
slot = int(input())
89-
90-
slot = slot + 100 # ECC keys in slot 101 - 132
91-
only_key.set_ecc_key(slot, (1+16+32+64+128), raw_privkey) #set ECC key with all features
92-
time.sleep(1.5)
93-
print(only_key.read_string())
94-
95-
elif sys.argv[1] == 'settime':
55+
if sys.argv[1] == 'settime':
9656
only_key.set_time(time.time())
9757

9858
elif sys.argv[1] == 'init':
@@ -281,6 +241,12 @@ def prompt_pin():
281241
elif sys.argv[1] == 'backupkey':
282242
only_key.generate_backup_key()
283243

244+
elif sys.argv[1] == 'setkey':
245+
only_key.setkey(sys.argv[2], sys.argv[3], sys.argv[4])
246+
247+
elif sys.argv[1] == 'wipekey':
248+
only_key.wipekey(sys.argv[2])
249+
284250
elif sys.argv[1] == 'idletimeout':
285251
only_key.setslot(1, MessageField.IDLETIMEOUT, int(sys.argv[2]))
286252
elif sys.argv[1] == 'wipemode':
@@ -307,7 +273,7 @@ def prompt_pin():
307273
else:
308274

309275
# Print help.
310-
print('OnlyKey CLI v1.2.0')
276+
print('OnlyKey CLI v1.2.1')
311277
print('Control-D to exit.')
312278
print()
313279

@@ -511,6 +477,18 @@ def mprompt():
511477
except:
512478
continue
513479

480+
elif data[0] == 'setkey':
481+
try:
482+
only_key.setkey(data[1], data[2], data[3])
483+
except:
484+
continue
485+
486+
elif data[0] == 'wipekey':
487+
try:
488+
only_key.wipekey(data[1])
489+
except:
490+
continue
491+
514492
elif data[0] == 'idletimeout':
515493
try:
516494
only_key.setslot(1, MessageField.IDLETIMEOUT, int(data[1]))

onlykey/client.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,11 @@ def set_time(self, timestamp):
216216
logging.debug('SENDING OKSETTIME:', [x for x in enumerate(payload)])
217217
self.send_message(msg=Message.OKSETTIME, payload=payload)
218218

219-
def set_ecc_key(self, key_type, slot, key):
220-
payload = [key_type, slot] + [ord(c) for c in key]
221-
self.send_message(msg=Message.OKSETPRIV, payload=payload)
222-
223-
def set_rsa_key(self, key_type, slot, key):
224-
payload = [key_type, slot] + [ord(c) for c in key]
225-
self.send_message(msg=Message.OKSETPRIV, payload=payload)
226-
227-
def send_message(self, payload=None, msg=None, slot_id=None, message_field=None):
219+
def send_message(self, payload=None, msg=None, slot_id=None, message_field=None, from_ascii=False):
228220
"""Send a message."""
229221
logging.debug('preparing payload for writing')
230222
# Initialize an empty message with the header
231-
raw_bytes = list(MESSAGE_HEADER)
223+
raw_bytes = bytearray(MESSAGE_HEADER)
232224

233225
# Append the message type (must be `Message` enum value)
234226
if msg:
@@ -249,9 +241,12 @@ def send_message(self, payload=None, msg=None, slot_id=None, message_field=None)
249241
if payload:
250242
if isinstance(payload, (str, str)):
251243
logging.debug('payload="%s"', payload)
252-
raw_bytes.extend(bytearray.fromhex(payload))
253-
elif isinstance(payload, list):
254-
logging.debug('payload=%s', ''.join([chr(c) for c in payload]))
244+
if from_ascii==True:
245+
raw_bytes.extend(str.encode(payload))
246+
else:
247+
raw_bytes.extend(bytearray.fromhex(payload))
248+
elif isinstance(payload, list) or isinstance(payload, bytearray):
249+
logging.debug('payload=%s', payload)
255250
raw_bytes.extend(payload)
256251
elif isinstance(payload, int):
257252
logging.debug('payload=%d', payload)
@@ -319,22 +314,17 @@ def send_large_message2(self, payload=None, msg=None, slot_id=101):
319314
return
320315

321316

322-
def send_large_message3(self, payload=None, msg=None, slot_id=101, key_type=1):
317+
def send_large_message3(self, payload=None, msg=None, key_type=None, slot_id=None):
323318
"""Wrapper for sending large message (larger than 58 bytes) in batch in a transparent way."""
324319
if not msg:
325320
raise Exception("Missing msg")
326321

327322
# Split the payload in multiple chunks
323+
payload = bytearray.fromhex(payload)
328324
chunks = [payload[x:x+MAX_LARGE_PAYLOAD_SIZE-1] for x in range(0, len(payload), 57)]
329325
for chunk in chunks:
330-
current_payload = [slot_id, key_type]
331-
332-
# Append the actual payload
333-
if isinstance(chunk, list):
334-
current_payload.extend(chunk)
335-
else:
336-
for c in chunk:
337-
current_payload.append(ord(c))
326+
current_payload = [int(slot_id), int(key_type)]
327+
current_payload = bytearray(bytes(current_payload)) + payload
338328
self.send_message(payload=current_payload, msg=msg)
339329
return
340330

@@ -436,9 +426,8 @@ def displaykeylabels(self):
436426
print(tmp[slot_name].to_str())
437427

438428
def setslot(self, slot_number, message_field, value):
439-
"""Set a slot field to the given value.
440-
"""
441-
self.send_message(msg=Message.OKSETSLOT, slot_id=slot_number, message_field=message_field, payload=value)
429+
"""Set a slot field to the given value."""
430+
self.send_message(msg=Message.OKSETSLOT, slot_id=slot_number, message_field=message_field, payload=value, from_ascii=True)
442431
# Set U2F
443432
# [255, 255, 255, 255, 230, 12, 8, 117, 50, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
444433
print(self.read_string())
@@ -449,6 +438,22 @@ def wipeslot(self, slot_number):
449438
for _ in range(8):
450439
print(self.read_string())
451440

441+
def setkey(self, slot_number, ecc_type, value):
442+
# slot 131-132 Reserved
443+
# slot 129-130 HMAC Keys
444+
# slot 101-116 ECC Keys
445+
# slot 1-4 RSA Keys
446+
logging.debug('SETTING KEY IN SLOT:', slot_number)
447+
logging.debug('TO TYPE:', ecc_type)
448+
logging.debug('KEY:', value)
449+
self.send_large_message3(msg=Message.OKSETPRIV, slot_id=slot_number, key_type=ecc_type, payload=value)
450+
print(self.read_string())
451+
452+
def wipekey(self, slot_number):
453+
logging.debug('WIPING KEY IN SLOT:', slot_number)
454+
self.send_large_message3(msg=Message.OKWIPEPRIV, slot_id=slot_number, key_type='00', payload='00')
455+
print(self.read_string())
456+
452457
def sign(self, SignatureHash):
453458
global slotnum
454459
print('Signature hash to send to OnlyKey= ', binascii.hexlify(SignatureHash))

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
setup(
1212
name='onlykey',
13-
version='1.2.0',
13+
version='1.2.1',
1414
description='OnlyKey client and command-line tool',
1515
# long_description=long_description,
1616
url='https://github.com/trustcrypto/python-onlykey',

0 commit comments

Comments
 (0)