I am trying to use DCAppAttestService in Xamarin.iOS to attest a key generatd with GenerateKeyAsync() in a real iOS device, but it is failing with this error:
The operation couldn’t be completed. (com.apple.devicecheck.error error 2.) Specified argument was out of the range of valid values. (Parameter 'Platform name: 5.')
Here is my code:
public async Task<byte[]> GetAttestObject(string Challenge)
{
DCAppAttestService atserv = DCAppAttestService.SharedService;
try
{
if (atserv.Supported)
{
var keyId = await atserv.GenerateKeyAsync();
var Sha256Challenge=Sha256(Challenge);//custom metod to hash.
var HashValue = NSData.FromString(Sha256Challenge);
var vas = await atserv.AttestKeyAsync(keyId, HashValue); //Error thrown here
MemoryStream ms = new MemoryStream();
vas.AsStream().CopyTo(ms);
return ms.ToArray();
}
else
return null;
}
catch (Exception ex)
{
var S = ex.Message;
return null;
}
}
I cannot find any example of using this service in Xamarin.iOS anywhere.
I can generate a device token without problems using: var tkn = await DCDevice.CurrentDevice.GenerateTokenAsync();
Can anyone tell me what I am doing wrong or show me a sample code to obtain the attest object?
Apple's docs indicate that
com.apple.devicecheck.error error 2is an issue with the input being invalid. https://developer.apple.com/documentation/devicecheck/dcerror/code/invalidinputCheck your
SHA256()method. Are you usingSystem.Security.Cryptography.SHA256, or something else to generate the hash? Is there are reason you're returning astringinstead of abyte[]?I'm not sure this will exactly help you in your specific case, however in my case, it was an issue with the
keyIdhaving been generated from a previous install of the app (Apple's docs say it should only be generated once per account per app and then stored and then reused, and we were putting it inXamarin.Essentials.SecureStorage(which equates to the KeyChain on iOS, which can persist between installs due to iCloud) to be retrieved when next required). SoDCAppAttestServiceconsiders thekeyIdto be invalid when the same one is used across app installs.Because you asked for a sample, here is the core parts of what I'm successfully using (leaving out the check that DCAppAttestService is supported on the device, and handling an exponential backoff when Apple's server is unavailable due to e.g. network conditions)