diff options
Diffstat (limited to 'source/storage/KeyManager.mc')
| -rw-r--r-- | source/storage/KeyManager.mc | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/source/storage/KeyManager.mc b/source/storage/KeyManager.mc index ebb0a62..567288f 100644 --- a/source/storage/KeyManager.mc +++ b/source/storage/KeyManager.mc @@ -33,6 +33,9 @@ class KeyManager { private var _store as Persist.Backend; private var _deviceKeys as SealedBox.Keys? = null; + private var _fingerprintKey as ByteArray? = null; + + static const FINGERPRINT_BYTES = 8; function initialize(store as Persist.Backend) { _store = store; @@ -55,11 +58,32 @@ class KeyManager { _store.setValue(DEVICE_KEY, raw); } keys = new SealedBox.Keys(raw); + _fingerprintKey = Kdf.hkdf(raw, []b, Bytes.fromUtf8("OTPW fp v1"), KEY_BYTES); Bytes.wipe(raw); _deviceKeys = keys; return keys; } + // An 8-byte keyed fingerprint of an entry's kind, type and secret (or + // payload): equal for duplicates, meaningless without the device key. + // Stored in the readable header so imports can find duplicates of locked + // entries while the watch is locked (docs/SECURITY.md). + function fingerprint(entry as Entry) as ByteArray { + deviceKeys(); + var input = Bytes.fromUtf8("OTPW-FP-1"); + input.add(entry.kind); + input.add(entry.type); + var material = entry.kind == Entry.KIND_OTP ? entry.secret : entry.payload; + if (material != null) { + input.addAll(material); + } + var mac = Hmac.nativeSha256(_fingerprintKey as ByteArray, input); + Bytes.wipe(input); + var out = mac.slice(0, FINGERPRINT_BYTES); + Bytes.wipe(mac); + return out; + } + // True when a PIN has been set. function hasPin() as Boolean { return _store.getValue(WRAP_KEY) != null; |
