iPhone에서 NSString에 대한 AES 암호화
누구든지 올바른 방향으로 문자열을 암호화하고 암호화 된 데이터로 다른 문자열을 반환 할 수 있습니까? (AES256 암호화를 사용해 보았습니다.) 두 개의 NSString 인스턴스를 사용하는 방법을 작성하고 싶습니다. 하나는 암호화 할 메시지이고 다른 하나는 암호화하는 '비밀번호'입니다. 암호가 암호화 된 데이터와 함께 제공되는 경우 되돌릴 수있는 방식으로 암호가있는 암호화 키. 그런 다음이 메소드는 암호화 된 데이터에서 생성 된 NSString을 반환해야합니다.
이 게시물의 첫 번째 주석에 설명 된 기술을 시도했지만 지금까지 운이 없었습니다. 애플의 CryptoExercise는 확실히 무언가를 가지고 있지만 이해할 수는 없습니다 ... CCCrypt 에 대한 많은 참조를 보았지만 그것을 사용한 모든 경우에 실패했습니다.
또한 암호화 된 문자열을 해독 할 수 있어야하지만 kCCEncrypt / kCCDecrypt처럼 간단하기를 바랍니다.
코드를 게시하지 않았기 때문에 어떤 문제가 발생했는지 정확히 알기가 어렵습니다. 그러나 링크 된 블로그 게시물 CCCrypt()
은 컴파일 오류를 일으킨 각 호출마다 여분의 쉼표를 제외하고는 꽤 괜찮은 것처럼 보입니다 .
해당 게시물에 대한 이후의 의견에는 이 적응 코드가 포함되어 있어 나에게 효과적이며 조금 더 직관적 인 것처럼 보입니다. NSData 범주에 대한 코드를 포함하면 다음과 같이 작성할 수 있습니다. (참고 : printf()
실제 응용 프로그램에서는 여러 지점에서 데이터 상태를 보여주기위한 호출입니다. 실제 응용 프로그램에서는 이러한 값을 인쇄하는 것이 적합하지 않습니다. .)
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *key = @"my password";
NSString *secret = @"text to encrypt";
NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
printf("%s\n", [[cipher description] UTF8String]);
plain = [cipher AES256DecryptWithKey:key];
printf("%s\n", [[plain description] UTF8String]);
printf("%s\n", [[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);
[pool drain];
return 0;
}
이 코드와 암호화 된 데이터가 항상 NSString으로 잘 변환되지는 않는다는 사실을 감안할 때 필요한 기능을 앞뒤로 래핑하는 두 가지 방법을 작성하는 것이 더 편리 할 수 있습니다 ...
- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
}
- (NSString*) decryptData:(NSData*)ciphertext withKey:(NSString*)key {
return [[[NSString alloc] initWithData:[ciphertext AES256DecryptWithKey:key]
encoding:NSUTF8StringEncoding] autorelease];
}
이것은 Snow Leopard에서 확실히 작동하며 @Boz 는 CommonCrypto가 iPhone의 핵심 OS의 일부 라고 보고합니다. 10.5에는 10.4와 10.4에 /usr/include/CommonCrypto
대한 맨 페이지가 있지만 CCCryptor.3cc
10.4에는 없습니다.
편집 : 안전하고 무손실 변환을 사용하여 암호화 된 데이터 바이트를 문자열 (원하는 경우)로 표시하기 위해 Base64 인코딩을 사용 하는 방법에 대한이 후속 질문 을 참조하십시오 .
나는 Jeff LaMarche의 블로그 에서 찾은 솔루션 과 Quinn Taylor의 스택 오버플로에 대한 힌트 를 사용하는 NSData 및 NSString의 범주 모음을 모았습니다 .
범주를 사용하여 NSData를 확장하여 AES256 암호화를 제공하고 암호화 된 데이터를 문자열로 안전하게 BASE64로 인코딩하도록 NSString의 확장을 제공합니다.
Here's an example to show the usage for encrypting strings:
NSString *plainString = @"This string will be encrypted";
NSString *key = @"YourEncryptionKey"; // should be provided by a user
NSLog( @"Original String: %@", plainString );
NSString *encryptedString = [plainString AES256EncryptWithKey:key];
NSLog( @"Encrypted String: %@", encryptedString );
NSLog( @"Decrypted String: %@", [encryptedString AES256DecryptWithKey:key] );
Get the full source code here:
Thanks for all the helpful hints!
-- Michael
@owlstead, regarding your request for "a cryptographically secure variant of one of the given answers," please see RNCryptor. It was designed to do exactly what you're requesting (and was built in response to the problems with the code listed here).
RNCryptor uses PBKDF2 with salt, provides a random IV, and attaches HMAC (also generated from PBKDF2 with its own salt. It support synchronous and asynchronous operation.
I waited a bit on @QuinnTaylor to update his answer, but since he didn't, here's the answer a bit more clearly and in a way that it will load on XCode7 (and perhaps greater). I used this in a Cocoa application, but it likely will work okay with an iOS application as well. Has no ARC errors.
Paste before any @implementation section in your AppDelegate.m or AppDelegate.mm file.
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AES256)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
- (NSData *)AES256DecryptWithKey:(NSString *)key {
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
@end
Paste these two functions in the @implementation class you desire. In my case, I chose @implementation AppDelegate in my AppDelegate.mm or AppDelegate.m file.
- (NSString *) encryptString:(NSString*)plaintext withKey:(NSString*)key {
NSData *data = [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
return [data base64EncodedStringWithOptions:kNilOptions];
}
- (NSString *) decryptString:(NSString *)ciphertext withKey:(NSString*)key {
NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];
return [[NSString alloc] initWithData:[data AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
}
참고URL : https://stackoverflow.com/questions/1400246/aes-encryption-for-an-nsstring-on-the-iphone
'programing tip' 카테고리의 다른 글
'ref'와 'out'이 다형성을 지원하지 않는 이유는 무엇입니까? (0) | 2020.07.10 |
---|---|
git update-index --skip-worktree 실행 취소 (0) | 2020.07.10 |
C #에서 'T : class'는 무엇을 의미합니까? (0) | 2020.07.10 |
선택적 매개 변수를 함수에 전달하는 방법이 있습니까? (0) | 2020.07.10 |
안드로이드 아카이브 라이브러리 (ar) vs 표준 jar (0) | 2020.07.10 |