반응형

최근 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

,