Я пишу плагин Nativescript, который выполняет вызовы к Android / Java Cipher и другим криптографическим классам. Мне нужно сохранить строку в цепочке для ключей, которая может быть сохранена / прочитана, только если пользователь прошел аутентификацию через TouchId или FaceId, и у меня работает TouchId / FaceId, но у меня возникают проблемы с выяснением, как хранить и читать строку.
У меня есть следующий код, который хранит строку, и это возможно работает (я не знаю, пока не попробую прочитать ее снова):
private createKeyChainEntry(data: string): boolean {
let attributes;
try {
attributes = NSMutableDictionary.new();
attributes.setObjectForKey(kSecClassGenericPassword, kSecClass);
attributes.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
attributes.setObjectForKey(this.keychainItemServiceName, kSecAttrService);
} catch (ex) {
console.trace(ex);
}
const accessControlRef = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
SecAccessControlCreateFlags.kSecAccessControlUserPresence,
null
);
if (accessControlRef === null) {
// console.log(`Can't store identifier '${keychainItemIdentifier}' in the KeyChain: ${accessControlError}.`);
console.log(`Can't store identifier '${keychainItemIdentifier}' in the KeyChain.`);
return false;
} else {
attributes.setObjectForKey(accessControlRef, kSecAttrAccessControl);
// The content of the password is not important
const content = NSString.stringWithString(data);
const nsData = content.dataUsingEncoding(NSUTF8StringEncoding);
attributes.setObjectForKey(nsData, kSecValueData);
SecItemAdd(attributes, null);
return true;
}
}
У меня также есть этот код, где я пытаюсь снова прочитать строку, но я не знаю, как получить фактическую строку из privKeyRef / resultData:
private readKeyChainEntry(): string {
let attributes;
try {
attributes = NSMutableDictionary.new();
attributes.setObjectForKey(kSecClassGenericPassword, kSecClass);
attributes.setObjectForKey(keychainItemIdentifier, kSecAttrAccount);
attributes.setObjectForKey(this.keychainItemServiceName, kSecAttrService);
attributes.setObjectForKey(true, kSecReturnData);
} catch (ex) {
console.trace(ex);
}
const accessControlRef = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
SecAccessControlCreateFlags.kSecAccessControlUserPresence,
null
);
console.log("readKeyChainEntry #3");
if (accessControlRef === null) {
// console.log(`Can't store identifier '${keychainItemIdentifier}' in the KeyChain: ${accessControlError}.`);
console.log(`Can't store identifier '${keychainItemIdentifier}' in the KeyChain.`);
return null;
} else {
console.log("readKeyChainEntry #4");
attributes.setObjectForKey(accessControlRef, kSecAttrAccessControl);
console.log("readKeyChainEntry #5");
const privKeyRef = new interop.Reference<any>();
let resultData: NSData;
let status = SecItemCopyMatching(attributes, privKeyRef);
console.log("readKeyChainEntry #6: " + status);
if (status == errSecSuccess) {
resultData = privKeyRef.value;
console.log("resultData: " + resultData);
console.log(NSString.new().initWithDataEncoding(resultData, NSUTF8StringEncoding));
}
}
return null;
}