def put(self, name, key, oath_type=TYPE_TOTP, algo=ALG_SHA1, digits=6, imf=0, always_increasing=False, require_touch=False): ensure_unlocked(self) key = hmac_shorten_key(key, algo) keydata = int2byte(oath_type | algo) + int2byte(digits) + key data = der_pack(TAG_NAME, name.encode('utf8'), TAG_KEY, keydata) properties = 0 if always_increasing: properties |= PROP_ALWAYS_INC if require_touch: if self.version < (4, 2, 6): raise Exception("Touch-required not supported on this key") properties |= PROP_REQUIRE_TOUCH if properties: data += int2byte(TAG_PROPERTY) + int2byte(properties) if imf > 0: data += der_pack(TAG_IMF, struct.pack('>I', imf)) self._send(INS_PUT, data) return Credential(self, oath_type, name)
def send_apdu(self, cl, ins, p1, p2, data): header = [cl, ins, p1, p2, len(data)] # from binascii import b2a_hex # print("SEND:", b2a_hex(''.join(map(int2byte, header)) + data)) resp, sw1, sw2 = self._conn.transmit(header + [byte2int(b) for b in data]) # print("RECV:", b2a_hex(b''.join(map(int2byte, resp + [sw1, sw2])))) return b''.join(int2byte(i) for i in resp), sw1 << 8 | sw2
def send_apdu(self, cl, ins, p1, p2, data): apdu = [cl, ins, p1, p2, len(data)] + [byte2int(b) for b in data] hresult, response = SCardTransmit(self._card, self._protocol, apdu) if hresult != SCARD_S_SUCCESS: raise Exception('Failed to transmit: ' + SCardGetErrorMessage(hresult)) status = response[-2] << 8 | response[-1] return b''.join(int2byte(i) for i in response[:-2]), status
def set_key(self, key=None): ensure_unlocked(self) if key: keydata = int2byte(TYPE_TOTP | ALG_SHA1) + key challenge = get_random_bytes(8) response = hmac_sha1(key, challenge) data = der_pack(TAG_KEY, keydata, TAG_CHALLENGE, challenge, TAG_RESPONSE, response) else: data = der_pack(TAG_KEY, b'') self._send(INS_SET_CODE, data)
def calculate(self, name, oath_type, timestamp=None): ensure_unlocked(self) c = self._device.conn.cursor() c.execute( 'SELECT "token","type","algorithm","digits","counter" FROM "tokens" WHERE "name" = ?', (name, )) key, oath_type, algo, digits, counter = c.fetchone() if oath_type == TYPE_TOTP: challenge = time_challenge(timestamp) elif oath_type == TYPE_HOTP: challenge = struct.pack('>q', counter) if algo == ALG_SHA1: h = hashes.SHA1() elif algo == ALG_SHA256: h = hashes.SHA256() elif algo == ALG_SHA512: h = hashes.SHA512() else: raise UnknownAlgorithmError key = decrypt_token(self._key, key) msg = challenge ctx = hmac.HMAC(key, h, backend=default_backend()) ctx.update(msg) response = ctx.finalize() offset = response[h.digest_size - 1] & 0xf code = response[offset:offset + 4] if name.startswith('Steam:'): scheme = SCHEME_STEAM else: scheme = SCHEME_STANDARD if oath_type == TYPE_HOTP: c.execute('UPDATE "tokens" SET "counter" = ? WHERE "name" = ?', (counter + 1, name)) self._device.conn.commit() return format_truncated(int2byte(digits) + code, scheme)
def der_pack(*values): return b''.join([int2byte(t) + int2byte(len(v)) + v for t, v in zip( values[0::2], values[1::2])])
def der_pack(*values): return b''.join([ int2byte(t) + int2byte(len(v)) + v for t, v in zip(values[0::2], values[1::2]) ])