SecKeyRawSign을 사용하여 일부 데이터에 서명하려고하지만 계속 -4 errSecUnimplemented가 표시됩니다. 설명서에는 iPhone OS2.0 이상에서 사용할 수 있다고 나와 있기 때문에 이상하게 보입니다.iPhone에서 SecKeyRawSign 사용
누구든지이 기능을 사용할 수 있습니까? 그렇다면 트릭이 관련되어 있습니까?
~ 네이트
SecKeyRawSign을 사용하여 일부 데이터에 서명하려고하지만 계속 -4 errSecUnimplemented가 표시됩니다. 설명서에는 iPhone OS2.0 이상에서 사용할 수 있다고 나와 있기 때문에 이상하게 보입니다.iPhone에서 SecKeyRawSign 사용
누구든지이 기능을 사용할 수 있습니까? 그렇다면 트릭이 관련되어 있습니까?
~ 네이트
-4 는 오류가 데이터 서명에 사용되는 개인 키에 대한 잘못된 참조에 의해 발생되고 있었다 errSecUnimplemented. 그 상황에 대한 혼란스러운 오류. errSecParam은 더 좋았을 것입니다.
~ 네이트
이 문제가 발생하는 경우 생성 된 개인 키가 실제로 키 체인에 저장되지 않기 때문에, 가장 가능성이 있습니다. 응용 프로그램을 중지했다가 다시 시작하고 메시지 서명이 작동하지 않을 때 이것을 알았습니다.
그래서이 작업을 수행하는 방법은 다음과 같습니다.
이 사람은 **
는 아이폰 OS 9이 새로운 기능을 도입 안전 영토라고- (void)generateKeyPair:(NSUInteger)keySize {
OSStatus sanityCheck = noErr;
publicKeyRef = NULL;
privateKeyRef = NULL;
LOGGING_FACILITY1(keySize == 512 || keySize == 1024 || keySize == 2048, @"%d is an invalid and unsupported key size.", keySize);
// First delete current keys.
[self deleteAsymmetricKeys];
// Container dictionaries.
// See SecKey.h for other values
NSDictionary *privateKeyDict = @{
(__bridge id) kSecAttrIsPermanent : [NSNumber numberWithBool:YES],
(__bridge id) kSecAttrApplicationTag : privateTag
};
// See SecKey.h for other values
NSDictionary *publicKeyDict = @{
(__bridge id) kSecAttrIsPermanent : [NSNumber numberWithBool:YES],
(__bridge id) kSecAttrApplicationTag : publicTag
};
NSDictionary *keyPairDict = @{
(__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA,
(__bridge id) kSecAttrKeySizeInBits : [NSNumber numberWithUnsignedInteger:keySize],
(__bridge id) kSecPrivateKeyAttrs : privateKeyDict,
(__bridge id) kSecPublicKeyAttrs : publicKeyDict
};
// SecKeyGeneratePair returns the SecKeyRefs
sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef) keyPairDict, &publicKeyRef, &privateKeyRef);
LOGGING_FACILITY(sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL, @"Something really bad went wrong with generating the key pair.");
// retrieve the actual bits for the keys, not just the references
NSData *publicKeyBits = [self getKeyBitsFromKey:publicKeyRef];
NSData *privateKeyBits = [self getKeyBitsFromKey:privateKeyRef];
// save the keys to the keychain
[self saveKeyToKeychain:publicKeyBits keySize:keySize private:NO];
[self saveKeyToKeychain:privateKeyBits keySize:keySize private:YES];
}
** 편집 키 쌍을 생성합니다. 그곳에 만 저장 될 키를 생성하려면 256-bit EC
키를 사용해야합니다. 영토가 지원하는 유일한 유형이므로 키를 사용해야합니다. keyPairDict
이 대신에 다음과 같이 표시됩니다
NSDictionary *keyPairDict = @{
(__bridge id)kSecAttrTokenID: (__bridge id)kSecAttrTokenIDSecureEnclave,
(__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeEC,
// we can use keySize here if we want
// but since 256 is the only available size
// we can just hardcode it for now
(__bridge id) kSecAttrKeySizeInBits : @256],
(__bridge id) kSecPrivateKeyAttrs : privateKeyDict,
(__bridge id) kSecPublicKeyAttrs : publicKeyDict
};
나는 매개 변수가 올바른지 알고 있지만 나 자신이 아직
안전 영토을 테스트하지, 그래서이 어떤 이유로 작동하지 않는 경우 알려주세요.
또한 참조 용으로는 256-bit EC
키는 3072-bit RSA
키와 같습니다.
도 다른 것 아래의 키를 검색하는 데 사용되는 쿼리 다음 안전 영토이기 때문에
NSDictionary *queryKey = @{
(__bridge id) kSecClass : (__bridge id) kSecClassKey,
(__bridge id) kSecAttrApplicationTag : tempTag,
(__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeEC
};
는, 음, 보안, 당신은 대부분 개인 키 비트를 검색 할 수 없습니다를 . 대부분의 경우 참조를 생성 할 수 있습니다. 하지만 어쨌든 개인 키 데이터를 처리 할 필요는 없습니다.이 방법은 체인의 실제 비트들을 검색하고, 다만 기준
- (NSData *)getKeyBitsFromKey:(SecKeyRef)givenKey {
static const uint8_t publicKeyIdentifier[] = "com.sample.temp";
NSData *tempTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
NSDictionary *queryKey = @{
(__bridge id) kSecClass : (__bridge id) kSecClassKey,
(__bridge id) kSecAttrApplicationTag : tempTag,
(__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA
};
// Temporarily add key to the Keychain, return as data:
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithDictionary:queryKey copyItems:YES];
[attributes setObject:(__bridge id) givenKey forKey:(__bridge id) kSecValueRef];
[attributes setObject:@YES forKey:(__bridge id) kSecReturnData];
// result codes: https://developer.apple.com/library/ios/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html#//apple_ref/doc/uid/TP30000157-CH4g-339030
OSStatus sanityCheck = noErr;
NSData *keyBits = nil;
CFTypeRef result;
sanityCheck = SecItemAdd((__bridge CFDictionaryRef) attributes, &result);
if (sanityCheck == errSecSuccess) {
keyBits = CFBridgingRelease(result);
// Remove from Keychain again:
(void) SecItemDelete((__bridge CFDictionaryRef) queryKey);
return keyBits;
}
else if (sanityCheck == errSecDuplicateItem) {
// Remove from Keychain again:
(void) SecItemDelete((__bridge CFDictionaryRef) queryKey);
return [self getKeyBitsFromKey:givenKey];
}
return nil;
}
이 방법 **
** END의 EDIT는 체인
- (void)saveKeyToKeychain:(NSData *)key keySize:(NSUInteger)keySize private:(BOOL)isPrivate {
OSStatus sanityCheck = noErr;
NSData *tag;
id keyClass;
if (isPrivate) {
tag = privateTag;
keyClass = (__bridge id) kSecAttrKeyClassPrivate;
}
else {
tag = publicTag;
keyClass = (__bridge id) kSecAttrKeyClassPublic;
}
NSDictionary *saveDict = @{
(__bridge id) kSecClass : (__bridge id) kSecClassKey,
(__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA,
(__bridge id) kSecAttrApplicationTag : tag,
(__bridge id) kSecAttrKeyClass : keyClass,
(__bridge id) kSecValueData : key,
(__bridge id) kSecAttrKeySizeInBits : [NSNumber numberWithUnsignedInteger:keySize],
(__bridge id) kSecAttrEffectiveKeySize : [NSNumber numberWithUnsignedInteger:keySize],
(__bridge id) kSecAttrCanDerive : (__bridge id) kCFBooleanFalse,
(__bridge id) kSecAttrCanEncrypt : (__bridge id) kCFBooleanTrue,
(__bridge id) kSecAttrCanDecrypt : (__bridge id) kCFBooleanFalse,
(__bridge id) kSecAttrCanVerify : (__bridge id) kCFBooleanTrue,
(__bridge id) kSecAttrCanSign : (__bridge id) kCFBooleanFalse,
(__bridge id) kSecAttrCanWrap : (__bridge id) kCFBooleanTrue,
(__bridge id) kSecAttrCanUnwrap : (__bridge id) kCFBooleanFalse
};
SecKeyRef savedKey = NULL;
sanityCheck = SecItemAdd((__bridge CFDictionaryRef) saveDict, (CFTypeRef *)&savedKey);
if (sanityCheck != errSecSuccess) {
LOGGING_FACILITY1(sanityCheck != noErr, @"Problem saving the key to keychain, OSStatus == %d.", sanityCheck);
}
}
으로 비트를 절약
다음과 같이 서명하십시오.
- (NSData *)getSignatureBytes:(NSData *)plainText {
OSStatus sanityCheck = noErr;
NSData *signedHash = nil;
uint8_t *signedHashBytes = NULL;
size_t signedHashBytesSize = 0;
SecKeyRef privateKey = NULL;
privateKey = [self getKeyRef:YES];
signedHashBytesSize = SecKeyGetBlockSize(privateKey);
// Malloc a buffer to hold signature.
signedHashBytes = malloc(signedHashBytesSize * sizeof(uint8_t));
memset((void *) signedHashBytes, 0x0, signedHashBytesSize);
// Sign the SHA1 hash.
sanityCheck = SecKeyRawSign(privateKey,
kTypeOfSigPadding,
(const uint8_t *) [[self getHashBytes:plainText] bytes],
kChosenDigestLength,
signedHashBytes,
&signedHashBytesSize
);
LOGGING_FACILITY1(sanityCheck == noErr, @"Problem signing the SHA1 hash, OSStatus == %d.", sanityCheck);
// Build up signed SHA1 blob.
signedHash = [NSData dataWithBytes:(const void *) signedHashBytes length:(NSUInteger) signedHashBytesSize];
if (signedHashBytes) {
free(signedHashBytes);
}
return signedHash;
}
iOS 9에서는 개인 키를 보안 영묘에 저장할 수 있습니다.이를 이용하려면 무엇이 필요합니까? (분명히 priv 키를 내보낼 수는 없지만 확인하는 것이 좋을 것입니다.) – LamonteCristo
@LamonteCristo 주석 상자가 더 제한되어 있기 때문에 위 질문에 대한 답변을 추가했습니다. – mikeho
@LamonteCristo 잠시 동안이 코드를 건드리지 않았으므로 기회가 생겼을 때 다시 살펴 보겠습니다. – mikeho
이것은 정확히 내가 가지고 있었던 문제였습니다. CryptoExercise의 SecKeyWrapper 클래스가 개인 키를 키 체인에 저장하지 못했다고 밝혀졌습니다. – mikeho