반응형

최근 SEED 블록 암호 알고리즘 CBC 암복호화 처리를

해야할 일이 생겨 관련 클래스를 제작하게 되었습니다

혹시 같은 작업을 하시는분에게 도움이 되었으면 합니다.

아래 작업은 Swift프로젝트에서 작업되었습니다.

 

SEED 블록암호 알고리즘

seed.kisa.or.kr/kisa/Board/17/detailView.do

 

KISA 암호이용활성화 - 암호알고리즘 소스코드

한국인터넷진흥원(KISA)에서는 128비트 블록암호 SEED를 쉽게 활용할 수 있도록, ECB, CBC, CTR, CCM, GCM, CMAC 운영모드에 대한 소스코드를 배포하고 있습니다. 언어 : C/C++, Java, ASP, JSP, PHP  다음글 2019-01-3

seed.kisa.or.kr

 

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

 

kelp404/CocoaSecurity

Encrypt/Decrypt: AES. Hash: MD5, SHA(SHA1, SHA224, SHA256, SHA384, SHA512). Encode/Decode: Base64, Hex. - kelp404/CocoaSecurity

github.com

 

해당 클래스도 프로젝트에 추가해 준다.

 

[ 사용방법 ] 

// 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/Tips] - ERROR: Could not get unknown property 'com' for root project 'myApp' of type org.gradle.api.Project

2020/07/11 - [Android/Tips] - error: cannot find symbol this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);

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) - 결과물 바이너리 검색

2020/06/03 - [iOS/Objective-C] - NSString <-> CBUUID

반응형

'개발 > 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
블로그 이미지

SKY STORY

,
반응형

KISA의 암호알고리즘을 이용한 Swift 프로젝트 셈플 입니다.

실제 프로젝트 사용 시 예제 (2/2)를 참고하세요.

 

SEED 블록암호 알고리즘 

seed.kisa.or.kr/kisa/Board/17/detailView.do

 

KISA 암호이용활성화 - 암호알고리즘 소스코드

한국인터넷진흥원(KISA)에서는 128비트 블록암호 SEED를 쉽게 활용할 수 있도록, ECB, CBC, CTR, CCM, GCM, CMAC 운영모드에 대한 소스코드를 배포하고 있습니다. 언어 : C/C++, Java, ASP, JSP, PHP  다음글 2019-01-3

seed.kisa.or.kr

 

KISA_SEED_CBC.h

다음 함수를 헤더에 선언해 주도록 한다.

extern int encryptSeedCBC( IN BYTE *pbszPlainText, OUT BYTE *pbszCipherText );
extern int decryptSeedCBC( IN BYTE *pbszCipherText, OUT BYTE *pbszPlainText );

 

KISA_SEED_CBC.c

아래 함수를 선언해 준다. 

void main(void) 함수는 제거한다.

// 초기화 벡터 - 사용자가 지정하는 초기화 벡터(16 BYTE)
BYTE pbszIV[16] = {0x026, 0x08d, 0x066, 0x0a7, 0x035, 0x0a8, 0x01a, 0x081, 0x06f, 0x0ba, 0x0d9, 0x0fa, 0x036, 0x016, 0x025, 0x001};

// 사용자가 지정하는 입력 키(16bytes), 암호화 대칭키
BYTE pbszUserKey[16] = {0x088, 0x0e3, 0x04f, 0x08f, 0x008, 0x017, 0x079, 0x0f1, 0x0e9, 0x0f3, 0x094, 0x037, 0x00a, 0x0d4, 0x005, 0x089};


int encryptSeedCBC( 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 *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;
}

 

Swift에서 사용하기 위해 KISA_SEED_CBC.h, KISA_SEED_CBC.c 파일들을 프로젝트에 추가한다.

SEED.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface SEED : NSObject

+(NSString *)encrypt:(NSString *)plainText;
+(NSString *)decrypt:(NSString *)cipherText;

@end

NS_ASSUME_NONNULL_END

 

SEED.mm

#import "SEED.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "KISA_SEED_CBC.h"


@implementation SEED

+(NSString *)encrypt:(NSString *)plainText {

    BYTE pbszPlainText[2048] = {0,};
    memset(pbszPlainText, 0, [plainText length]);
    const char *byteBuff = [msg UTF8String];
    memcpy(pbszPlainText, (BYTE *)byteBuff, strlen(byteBuff));
    
    // 암호문 출력 버퍼
    BYTE pbszCipherText[2048] = {0,};
    int nCipherTextLen = encryptSeedCBC( 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]);
    
    // log
    [SEED printHexaLog:pbszCipherText length:nCipherTextLen];

    return base64String;
}

+(NSString *)decrypt:(NSString *)cipherText {

    // base64 decode
    NSData *data = [[NSData alloc] initWithBase64EncodedString:cipherText options:0];

    BYTE pbszCipherText[2048] = {0,};
    memcpy(pbszCipherText, [data bytes], [data length]);
    
    // 사용자 입력 평문
    BYTE pbszPlainText[2048] = {0,};
    int nPlainTextLen = decryptSeedCBC( pbszCipherText, pbszPlainText );
    
    NSString *plainText = [[NSString alloc] initWithBytes:pbszPlainText length:nPlainTextLen encoding:NSUTF8StringEncoding];
    
    // memory clean
    memset(pbszCipherText, 0, nPlainTextLen);
    
    // log
    [SEED printHexaLog:pbszPlainText length:nPlainTextLen];
    
    return plainText;
}

+(void)printHexaLog:(BYTE *)pbBytes length:(NSInteger)length {
    printf ("\nLength (%ld)  : ", (long)length);
    for (int i=0;i<length;i++) {
        printf("%02X ",pbBytes[i]);
    }
}

@end

 

Swift 프로젝트에 추가하고 Bridging Header 생성

#import "SEED.h"

 

사용방법 :

let str = "hello world"
let enc = SEED.encrypt(str)
print("\nenc = \(enc)")
let dec = SEED.decrypt(enc)
print("\ndec = \(dec)")

 

결과 :

---------------------------------
plainText : hello world

---------------------------------
SEED CBC Encryption....

Length (16)  : 53 81 F3 E0 18 41 85 70 29 3F 98 8F 9A A1 84 06 
enc = U4Hz4BhBhXApP5iPmqGEBg==

---------------------------------
SEED CBC Decryption....

Length (11)  : 68 65 6C 6C 6F 20 77 6F 72 6C 64 
dec = hello world

 

2020/07/11 - [분류 전체보기] - SEED 블록암호 알고리즘 CBC (Cipher Block Chaining) 예제2

2020/05/28 - [개발노트] - HMAC SHA256

2020/05/26 - [iOS/Swift] - Array <-> Data

2020/05/25 - [분류 전체보기] - UserAgent 추가

2020/05/25 - [iOS/Swift] - RSA 암호화 / 복호화

2020/05/25 - [iOS/Swift] - Base64 인코딩/디코딩

2020/05/19 - [AI/Algorithm] - Generic algorithm

2020/05/19 - [AI/Algorithm] - neural network

2020/05/19 - [AI/Algorithm] - minimax full search example

2020/05/19 - [AI/Algorithm] - minimax, alpha-beta pruning

2020/05/19 - [iOS/Tips] - Bitbucket Carthage 사용

2020/05/19 - [iOS/Jailbreak] - Fridump 사용법 (3/3) - 메모리 덤프

2020/05/19 - [iOS/Jailbreak] - Fridump 사용법 (2/3) - Mac OS X 환경 구축

2020/05/19 - [iOS/Jailbreak] - Fridump 사용법 (1/3) - iOS디바이스 환경 구축

2020/05/19 - [iOS/Jailbreak] - Fridump, Tcpdump, OpenSSL Quick Guide

2020/05/19 - [OS/Mac OS X] - gdb 사용

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'개발 > iOS' 카테고리의 다른 글

Merge two different images in swift  (0) 2020.05.29
NSString <-> CBUUID 변환  (0) 2020.05.29
Array <-> Data 변환  (0) 2020.05.26
UserAgent 변경/추가  (0) 2020.05.25
RSA 암호화 / 복호화  (0) 2020.05.25
블로그 이미지

SKY STORY

,