해싱(Hashing)
- 목적: 입력 데이터를 고정된 크기의 고유한 해시 값으로 변환해서 데이터를 식별하거나 무결성을 확인.
- 특징: 단방향 함수로, 해시 값으로부터 원래 데이터를 복원할 수 없다.
- 사용 사례:
- 데이터 무결성 확인: 파일의 해시 값을 저장해두고, 나중에 동일한 해시 값을 생성하여 데이터가 변경되지 않았음을 확인.
- 비밀번호 저장: 비밀번호를 해시 값으로 변환하여 저장함으로써, 실제 비밀번호를 저장하지 않고도 비밀번호 검증이 가능.
- 디지털 서명: 문서의 해시 값을 서명하여, 문서의 변경 여부를 검증.
- 종류:
- MD5, SHA-1,SHA256 등 현재는 SHA256을 가장 많이 사용한다.
SHA-256 (Secure Hash Algorithm 256-bit)
-
- 길이: 256비트 해시 값 생성
- 특징: SHA-2 계열에 속하며, 현재 널리 사용되는 안전한 해시 함수
- 사용 예시: 비밀번호 저장, 디지털 서명, 블록체인
SHA256 해싱 알고리즘 예시
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
NSString *sha256String(NSString *input) {
const char *s = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(keyData.bytes, (CC_LONG)keyData.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
//NSData로 반환
NSData *sha256Data(NSString *input) {
const char *s = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(keyData.bytes, (CC_LONG)keyData.length, digest);
return [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}
int main(void)
{
@autoreleasepool {
NSString *pw= @"Hello SHA";
NSString *hashed = sha256String(pw);
NSLog(@"%@", hashed);
//4ea3b17f124867y1294ffad~~~
}
return 0;
}
SHA256 알고리즘을 통해 간단한 문자열을 해시값으로 바꾸는 예시이다.
암호화 알고리즘
데이터를 인코딩해서 키가 있는 사람만 복호화 할 수 있도록 하는 방법이다.
크게 대칭 키 암호화와 비대칭 키 암호화로 나눌 수 있다.
AES (Advanced Encryption Standard)
- 키 길이: 128비트, 192비트, 256비트
- 특징: 높은 보안성을 제공하며, 현재 표준으로 널리 사용됨
- 사용 예시: 데이터베이스 암호화, 파일 암호화, 네트워크 통신 보안
AES는 대표적인 대칭 키 암호화 알고리즘으로,
'하나의 비밀 키'를 사용해서 데이터를 암호화하고 복호화 한다.
사물함을 여는 열쇠와 닫는 열쇠가 하나로 같다고 비유할 수 있다.
AES 데이터 암호화 예시
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonCrypto.h>
// SHA-256 해시(대칭 키 해시처리, NSData 리턴)
NSData *sha256Data(NSString *input) {
const char *s = [input cStringUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(keyData.bytes, (CC_LONG)keyData.length, digest);
return [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}
AES 암호화
// AES 암호화
NSData *aesEncrypt(NSData *data, NSData *key) {
size_t outLength;
NSMutableData *cipherData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding,
key.bytes, kCCKeySizeAES256,
NULL,
data.bytes, data.length,
cipherData.mutableBytes, cipherData.length,
&outLength);
if (result == kCCSuccess) {
cipherData.length = outLength;
} else {
return nil;
}
return cipherData;
}
AES 복호화
// AES 복호화
NSData *aesDecrypt(NSData *data, NSData *key) {
size_t outLength;
NSMutableData *decryptedData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
CCCryptorStatus result = CCCrypt(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding,
key.bytes, kCCKeySizeAES256,
NULL,
data.bytes, data.length,
decryptedData.mutableBytes, decryptedData.length,
&outLength);
if (result == kCCSuccess) {
decryptedData.length = outLength;
} else {
return nil;
}
return decryptedData;
}
AES 암호화 후 복호화
int main(void) {
@autoreleasepool {
NSString *myData = @"myData";
NSData *encodedData = [myData dataUsingEncoding:NSUTF8StringEncoding];
NSString *pw = @"myPassword";
NSData *keyData = sha256(pw);
NSData *encryptedData = aesEncrypt(encodedData, keyData);
NSData *decryptedData = aesDecrypt(encryptedData, keyData);
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
NSLog(@"AES 암호화 됨: %@", encryptedData);
// {length = ~~, bytes = @xf31939afds~~}
NSLog(@"AES 복호화 됨: %@", decryptedString); //myData
}
}
RSA (Rivest–Shamir–Adleman)
- 키 길이: 일반적으로 2048비트 또는 4096비트
- 특징: 공개 키로 암호화하고 개인 키로 복호화할 수 있음. 키 관리가 복잡하지만 높은 보안성 제공
- 사용 예시: 데이터 전송 보안, 디지털 서명
RSA는 대표적인 비대칭 키 암호화 알고리즘으로,
공개 키와 개인 키 두개의 키를 사용해서 데이터 암호화와 복호화를 수행한다.
사물함을 잠구는 열쇠와 사물함을 여는 열쇠가 따로 있다고 비유할 수 있다.
공개키, 비밀키 생성
(Deprecated된 것이 좀 있고, 파라미터 전달 방식이 꽤 다양했는데 그냥 키사이즈만 전달하는 방식으로 작성함)
#import <CommonCrypto/CommonCrypto.h>
#import <Security/Security.h>
SecKeyRef generatePrivateKey(int keySize) {
NSDictionary *attributes = @{
(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
(id)kSecAttrKeySizeInBits: @(keySize)
};
CFErrorRef error = NULL;
SecKeyRef privateKeyRef = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &error);
if (!privateKeyRef) {
NSError *err = CFBridgingRelease(error);
NSLog(@"비공개키 생성 실패: %@", err.localizedDescription);
return NULL;
}
return privateKeyRef;
}
-> 비공개키를 생성하고 반환하면 여기서 공개키를 copy(추출)해서 사용
RSA 암호화
NSData *rsaEncrypt(NSData *data, SecKeyRef publicKey) {
CFErrorRef error = NULL;
NSData *cipherData = (NSData *)CFBridgingRelease(
SecKeyCreateEncryptedData(publicKey,
kSecKeyAlgorithmRSAEncryptionPKCS1,
(__bridge CFDataRef)data,
&error)
);
if (error) {
NSError *err = CFBridgingRelease(error);
NSLog(@"Encryption error: %@", err.localizedDescription);
return nil;
}
return cipherData;
}
RSA 복호화
NSData * rsaDecrypt(NSData *encryptedData, SecKeyRef privateKey) {
CFErrorRef error = NULL;
NSData *plainData = (NSData *)CFBridgingRelease(
SecKeyCreateDecryptedData(privateKey, kSecKeyAlgorithmRSAEncryptionPKCS1,
(__bridge CFDataRef)cipherData, &error));
if (error) {
NSError *err = CFBridgingRelease(error);
NSLog(@"복호화 에러: %@", err.localizedDescription);
return nil;
}
return plainData;
}
RSA 암호화 및 복호화 테스트
int main(void) {
@autoreleasepool {
NSString *data = @"myData";
NSData *encodedData = [data dataUsingEncoding: NSUTF8StringEncoding];
SecKeyRef privateKey = generatePrivatKey(2048);
SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);
//암호화
NSData *encryptedData = rsaEncrypt(encodedData, publicKey);
NSData *decryptedData = rsaDecrypt(encryptedData, privateKey);
NSLog(@"encrypted: %@", encryptedData) // {length = 256, bytes = 0x0e723fa9 38344f8d ...}
NSLog(@"decrypted: %@", [[NSString alloc] initWithData: decryptedData encoding: NSUTF8StringEncoding]); //myData
}
}
주민등록번호 등 데이터 암호화가 필요한 부분에서 자주 쓰이는 암호화에 대해 간단하게 알아보았다.
실제로 적용할 때는 더 자세한 에러처리, 데이터 관리 등의 로직이 추가되겠지만
기본적으로 AES가 단일 키 방식, RSA는 다중 키(개인 키, 공개 키)방식으로 암호화 및 복호화가 이루어진다는 것,
Objective-C환경에서 CommonCrypto와 Security를 사용한다는 것을 알 수 있었다.
'UIKit > UIKit' 카테고리의 다른 글
Objective-C 생체 인증(Bio Authentication) (0) | 2024.06.04 |
---|---|
Objective-C 카메라, 앨범 권한 요청 (0) | 2024.06.04 |
Objective-C 코드 베이스 세팅 (0) | 2024.06.04 |
init(frame:) & init(coder:) (0) | 2023.04.11 |
DequeueReusableCell ?? 테이블뷰와 셀 (0) | 2023.02.28 |