public class SecureStorageDeviceProtection
- Object
- DeviceProtection
- SecureStorageDeviceProtection
The DeviceProtection every port gets when it does not supply one of its own: a random
wrapping key in SecureStorage, and AES-GCM performed in shared code.
This is the right implementation wherever SecureStorage is the operating system’s secret
store – the iOS keychain, the Android keystore, the desktop credential store. The wrapping
key is bytes, and it is bytes in the one place on the device that is built to hold bytes
nobody else should reach.
It is the wrong implementation in a browser, where SecureStorage is ordinary
origin-private storage: the wrapping key would sit beside the ciphertext it protects, which is
no protection at all. The JavaScript port therefore overrides
CodenameOneImplementation.getDeviceProtection with one built on a
non-extractable CryptoKey, and this class never runs there.
Racing callers
Key creation goes through SecureStorage.setIfAbsent(String, String), which returns what the
store ended up holding rather than what this call wrote. Two processes that both find nothing
therefore agree on one key instead of each overwriting the other – which matters more here
than almost anywhere, because the loser’s key is what a device’s remembered vault was wrapped
under.
Constructors
public SecureStorageDeviceProtection() |
Methods
protected SecureStorage storage() | The store backing this. |
public ProtectionReport protection() | What this device protection actually provides, as observed rather than as advertised. |
public int keyState(String keyId) | Whether a device key exists for this id. |
public AsyncResource<Boolean> ensureKey(String keyId) | Creates the device key if there is none, and converges when two callers race. |
public AsyncResource<byte[]> wrap(String keyId, byte[] plaintext, byte[] aad) | Encrypts under the device key. |
public AsyncResource<byte[]> unwrap(String keyId, byte[] wrapped, byte[] aad) | Decrypts what wrap produced. |
public AsyncResource<Boolean> deleteKey(String keyId) | Removes the device key, which is what “forget this device” does. |
Inherited fields
Inherited methods
Constructor details
SecureStorageDeviceProtection
public SecureStorageDeviceProtection()Method details
storage
protected SecureStorage storage()SecureStorage.getInstance() returns, which the simulator’s test harness uses.protection
public ProtectionReport protection()What this device protection actually provides, as observed rather than as advertised.
A port that has not yet tried an operation may only report what it can verify; several
answers are legitimately ProtectionReport.UNKNOWN – no browser can say whether a key
is hardware backed, and reporting NO there would understate an authenticator that uses a
secure element.
keyState
public int keyState(String keyId)Parameters
keyIdString- the vault’s device key id
Returns
ensureKey
public AsyncResource<Boolean> ensureKey(String keyId)Parameters
keyIdString- the vault’s device key id
Returns
true when a key is in place – whether this call created it
or found another one already there – and erroring with a
VaultException when no key could be establishedwrap
public AsyncResource<byte[]> wrap(String keyId, byte[] plaintext, byte[] aad)Parameters
keyIdString- the vault’s device key id
plaintextbyte[]- what to protect, normally a vault’s 32 byte data key
aadbyte[]- associated data the result is bound to; the same bytes must be supplied to
unwrap
Returns
unwrap
public AsyncResource<byte[]> unwrap(String keyId, byte[] wrapped, byte[] aad)Decrypts what wrap produced.
A failure to authenticate must arrive as
VaultError.AUTHENTICATION_FAILED, a missing key as
VaultError.KEY_MISSING, and a store that could not be read
as VaultError.TEMPORARILY_UNREADABLE. Collapsing the last
two is how a vault regenerates a key and orphans its data.
deleteKey
public AsyncResource<Boolean> deleteKey(String keyId)Removes the device key, which is what “forget this device” does.
Everything wrapped under it becomes unopenable on this device. That is the intent; it is not revocation, because a copy taken while the key existed is beyond reach.