최근 SEED 블록 암호 알고리즘 CBC 암복호화 처리를
해야할 일이 생겨 관련 클래스를 제작하게 되었습니다
혹시 같은 작업을 하시는분에게 도움이 되었으면 합니다.
아래 작업은 Swift프로젝트에서 작업되었습니다.
SEED 블록암호 알고리즘
seed.kisa.or.kr/kisa/Board/17/detailView.do
KISA_SEED_CBC.h
다음 함수를 헤더에 선언해 주도록 한다.
extern int encryptSeedCBC( IN BYTE *pbszUserKey, IN BYTE *pbszIV, IN BYTE *pbszPlainText, OUT BYTE *pbszCipherText );
extern int decryptSeedCBC( IN BYTE *pbszUserKey, IN BYTE *pbszIV, IN BYTE *pbszCipherText, OUT BYTE *pbszPlainText );
KISA_SEED_CBC.c
다음과 같이 작성해 준다.
작성에 앞서 main()함수는 제거해주도록 하자.
int encryptSeedCBC( IN BYTE *pbszUserKey, IN BYTE *pbszIV, IN BYTE *pbszPlainText, OUT BYTE *pbszCipherText )
{
printf("\n---------------------------------");
printf("\nplainText : %s\n", (char *)pbszPlainText);
int nPlainTextLen = (int)strlen((char *)pbszPlainText);// 평문의 Byte길이
printf ("\n---------------------------------");
printf ("\nSEED CBC Encryption....\n");
// 암호문의 Byte길이 - 패딩 로직때문에 16바이트 블럭으로 처리함으로 pbszCipherText는 평문보다 16바이트 커야 한다.
int nCipherTextLen = SEED_CBC_Encrypt( pbszUserKey, pbszIV, pbszPlainText, nPlainTextLen, pbszCipherText );
return nCipherTextLen;
}
int decryptSeedCBC( IN BYTE *pbszUserKey, IN BYTE *pbszIV, IN BYTE *pbszCipherText, OUT BYTE *pbszPlainText )
{
int nCipherTextLen = (int)strlen((char *)pbszCipherText);// 암호문의 Byte길이
printf ("\n---------------------------------");
printf ("\nSEED CBC Decryption....\n");
// 평문의 Byte길이
int nPlainTextLen = SEED_CBC_Decrypt( pbszUserKey, pbszIV, pbszCipherText, nCipherTextLen, pbszPlainText );
return nPlainTextLen;
}
CryptoUtil 유틸 클래스 생성
//
// CryptoUtil.h
//
//
// Created by netcanis on 2020/07/09.
// Copyright © 2020 netcanis. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface CryptoUtil : NSObject
+(NSString *)encrypt:(NSString *)masterKey msg:(NSString *)msg;
+(NSString *)encrypt:(Byte *)key iv:(Byte *)iv msg:(NSString *)msg;
+(NSString *)decrypt:(NSString *)masterKey msg:(NSString *)base64Str;
+(NSString *)decrypt:(Byte *)key iv:(Byte *)iv msg:(NSString *)base64Str;
+(NSData *)getSHA256:(NSString *)msg;
+(NSString *)hash:(NSString *)secret payload:(NSString *)payload;
@end
NS_ASSUME_NONNULL_END
//
// CryptoUtil.m
//
//
// Created by netcanis on 2020/07/09.
// Copyright © 2020 netcanis. All rights reserved.
//
#import "CryptoUtil.h"
#import "CocoaSecurity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "KISA_SEED_CBC.h"
@implementation CryptoUtil
+(NSString *)encrypt:(NSString *)masterKey msg:(NSString *)msg {
NSData *sha256 = [self getSHA256:masterKey];
NSData *key = [sha256 subdataWithRange:NSMakeRange(0, 16)];
NSData *iv = [sha256 subdataWithRange:NSMakeRange(16, 16)];
BYTE pbszPlainText[2048] = {0,};
memset(pbszPlainText, 0, [msg length]);
const char *byteBuff = [msg UTF8String];
memcpy(pbszPlainText, (BYTE *)byteBuff, strlen(byteBuff));
// 암호문 출력 버퍼
BYTE pbszCipherText[2048] = {0,};
int nCipherTextLen = encryptSeedCBC( (BYTE *)[key bytes], (BYTE *)[iv bytes], pbszPlainText, pbszCipherText );
// base64 encode
NSData *data = [[NSData alloc] initWithBytes:pbszCipherText length:nCipherTextLen];
NSString *base64String = [data base64EncodedStringWithOptions:0];
// memory clean
memset(pbszPlainText, 0, nCipherTextLen);
memset((void *)[data bytes], 0, [data length]);
#ifdef DEBUG
// log
[CryptoUtil printHexaLog:pbszCipherText length:nCipherTextLen];
#endif//DEBUG
return base64String;
}
+(NSString *)encrypt:(Byte *)key iv:(Byte *)iv msg:(NSString *)msg {
BYTE pbszPlainText[2048] = {0,};
memset(pbszPlainText, 0, [msg length]);
const char *byteBuff = [msg UTF8String];
memcpy(pbszPlainText, (BYTE *)byteBuff, strlen(byteBuff));
// 암호문 출력 버퍼
BYTE pbszCipherText[2048] = {0,};
int nCipherTextLen = encryptSeedCBC( key, iv, pbszPlainText, pbszCipherText );
// base64 encode
NSData *data = [[NSData alloc] initWithBytes:pbszCipherText length:nCipherTextLen];
NSString *base64String = [data base64EncodedStringWithOptions:0];
// memory clean
memset(pbszPlainText, 0, nCipherTextLen);
memset((void *)[data bytes], 0, [data length]);
#ifdef DEBUG
// log
[CryptoUtil printHexaLog:pbszCipherText length:nCipherTextLen];
#endif//DEBUG
return base64String;
}
+(NSString *)decrypt:(NSString *)masterKey msg:(NSString *)base64Str {
NSData *sha256 = [self getSHA256:masterKey];
NSData *key = [sha256 subdataWithRange:NSMakeRange(0, 16)];
NSData *iv = [sha256 subdataWithRange:NSMakeRange(16, 16)];
// base64 decode
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Str options:0];
BYTE pbszCipherText[2048] = {0,};
memcpy(pbszCipherText, [data bytes], [data length]);
// 사용자 입력 평문
BYTE pbszPlainText[2048] = {0,};
int nPlainTextLen = decryptSeedCBC( (BYTE *)[key bytes], (BYTE *)[iv bytes], pbszCipherText, pbszPlainText );
NSString *plainText = [[NSString alloc] initWithBytes:pbszPlainText length:nPlainTextLen encoding:NSUTF8StringEncoding];
// memory clean
memset(pbszCipherText, 0, nPlainTextLen);
#ifdef DEBUG
// log
[CryptoUtil printHexaLog:pbszPlainText length:nPlainTextLen];
#endif//DEBUG
return plainText;
}
+(NSString *)decrypt:(Byte *)key iv:(Byte *)iv msg:(NSString *)base64Str {
// base64 decode
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Str options:0];
BYTE pbszCipherText[2048] = {0,};
memcpy(pbszCipherText, [data bytes], [data length]);
// 사용자 입력 평문
BYTE pbszPlainText[2048] = {0,};
int nPlainTextLen = decryptSeedCBC( key, iv, pbszCipherText, pbszPlainText );
NSString *plainText = [[NSString alloc] initWithBytes:pbszPlainText length:nPlainTextLen encoding:NSUTF8StringEncoding];
// memory clean
memset(pbszCipherText, 0, nPlainTextLen);
#ifdef DEBUG
// log
[CryptoUtil printHexaLog:pbszPlainText length:nPlainTextLen];
#endif//DEBUG
return plainText;
}
+(NSData *)getSHA256:(NSString *)msg {
NSData *data = [CocoaSecurity sha256:msg].data;
return data;
}
+(NSString *)hash:(NSString *)secret payload:(NSString *)payload {
NSString *result = [CocoaSecurity hmacSha256:payload hmacKey:secret].base64;
return result;
}
+(void)printHexaLog:(BYTE *)pbBytes length:(NSInteger)length {
printf ("\nLength (%ld) : ", (long)length);
for (int i=0;i<length;i++) {
printf("%02X ",pbBytes[i]);
}
}
@end
암호화 처리를 위해 CocoaSecurity 클래스를 사용했다.
https://github.com/kelp404/CocoaSecurity/tree/master/CocoaSecurity
해당 클래스도 프로젝트에 추가해 준다.
[ 사용방법 ]
// encode
let msg = "2020070917085299920190520000001abcdefghijklmn"
let masterKey = "1234567890";
let enc = CryptoUtil.encrypt(masterKey, msg: msg)
print("\(enc)")
// output :
3JomiSXGgIuC6vbFELbIa3+5QyJlpv6cFgy6JDcPmRryk2V+y2sueCivAymkra6D
// decode
let dec = CryptoUtil.decrypt(masterKey, msg: enc)
// output :
2020070917085299920190520000001abcdefghijklmn
2020/07/11 - [분류 전체보기] - SEED 블록암호 알고리즘 CBC (Cipher Block Chaining) 예제2
2020/07/11 - [Android/Java] - Webview에서 새로운창 출력
2020/07/11 - [Android/Tips] - Could not find com.android.tools.build:aapt2:4.0.0-6051327.
2020/07/11 - [Android/Kotlin] - byte array to hex string
2020/07/11 - [Android/Tips] - Android API Level 및 명칭
2020/07/11 - [Android/Rooting] - LG 펌웨어 추출 및 OS 다운그레이드 (kdz file)
2020/07/11 - [Android/Rooting] - 안드로이드 Fridump 환경설정 (4/4)
2020/07/11 - [Android/Rooting] - 안드로이드 Fridump 환경설정 (3/4)
2020/07/11 - [Android/Rooting] - 안드로이드 Fridump 환경설정 (2/4)
2020/07/11 - [Android/Rooting] - 안드로이드 Fridump 환경설정 (1/4)
2020/06/16 - [OS/Mac OS X] - duplicate symbol 에러 해결
2020/06/12 - [iOS/Jailbreak] - Fridump 사용법 (4/4) - 결과물 바이너리 검색
'개발 > iOS' 카테고리의 다른 글
Dictionary sort (0) | 2020.07.11 |
---|---|
UTC시간, Locale시간 변경 (0) | 2020.07.11 |
Fridump 사용법 (4/4) - 결과물 바이너리 검색 (0) | 2020.06.12 |
NSString <-> CBUUID (0) | 2020.06.03 |
위치서비스(location service) 활성화 여부 체크 (0) | 2020.06.03 |