我正在绞尽脑汁地尝试实现我认为非常基本的功能:将键值对存储在 Delphi iOS 应用程序的钥匙串中。 (在毛伊岛的世界里,使用 SecureStorage 是微不足道的,但我在 Delphi 中没有找到等效的包装器。如果有人知道,请告诉我!)
我已经浏览了Apple文档,以及我可以在网上找到的任何示例,但是在存储时我遇到了kSecParam错误。
这是我迄今为止尝试过的一些代码:
function SaveToKeychain(const Key, Value: string) : Boolean;
var
query, attributes: NSMutableDictionary;
status: OSStatus;
keyData, valueData: NSData;
Data: CFDataRef;
valueBytes : TBytes;
testStr : String;
begin
Result := False;
try
query := TNSMutableDictionary.Create;
try
valueBytes := TEncoding.UTF8.GetBytes(Value);
//valueData := TNSData.Wrap(TNSData.alloc.initWithBytesNoCopy(@Value[1], Length(Value)));
//Data := CFDataCreate(nil, @Value[1], Length(Value) * SizeOf(Char));
try
// Define the keychain item attributes
query.setValue((kSecClassGenericPassword as ILocalObject).GetObjectID, kSecClass);
query.setValue((StrToNSStr(key) as ILocalObject).GetObjectID, kSecAttrAccount);
//query.setValue(Data, StrToNSStr('kSecValueData'));
query.setValue((StrToNSStr(Value) as ILocalObject).GetObjectID, StrToNSStr('kSecValueData'));
// Add the item to the keychain
status := SecItemAdd((query as ILocalObject).GetObjectID, nil);
finally
CFRelease(Data);
end;
AddToLog(Format('SaveToKeychain status: %d', [status]));
Result := (status = errSecSuccess);
finally
query.Release;
end;
except
on E:Exception do
AddToLog('Error in SaveToKeychain: ' + E.Message);
end;
end;
SecItemAdd 调用返回 kSecParam 错误,这意味着一个或多个参数/属性不正确。我假设这是数据,所以我尝试了几种添加它的方法,但没有成功。
我错过了什么??
我对有关 kSecValueData 问题的评论不太正确,因为我错过了第二个参数需要对象 ID。此外,这还不够:
StrToNSStr('kSecValueData')
因为常数实际上可能不等于该值。这段代码应该可以工作:
uses
Macapi.CoreFoundation, Macapi.Helpers, Macapi.ObjectiveC,
iOSapi.Foundation, iOSapi.Security;
function kSecValueData: NSString;
begin
Result := CocoaNSStringConst(libSecurity, 'kSecValueData');
end;
function SaveToKeychain(const Key, Value: string) : Boolean;
var
query: NSMutableDictionary;
status: OSStatus;
begin
Result := False;
try
query := TNSMutableDictionary.Create;
query.setObject(NSObjectToID(kSecClassGenericPassword), NSObjectToID(kSecClass));
query.setObject(StringToID(key), NSObjectToID(kSecAttrAccount));
query.setObject(NSObjectToID(StrToNSStr(Value).dataUsingEncoding(NSUTF8StringEncoding)), NSObjectToID(kSecValueData));
status := SecItemAdd(NSObjectToID(query), nil);
Log.d('SaveToKeychain status: %d', [status]);
Result := (status = errSecSuccess);
except
on E:Exception do
Log.d('Error in SaveToKeychain: ' + E.Message);
end;
end;