암호화 프로그래밍 정리

유창훈

목차

1AES

1.1EVP(open ssl)

<암호화>

#include <openssl/evp.h

#include <openssl/err.h
#include <openssl/ssl.h
/* AES Encrypt Process */
intencrypt_block(unsigned char* cipherText, unsigned char* plainText, unsigned intplainTextLen, unsigned char* key)
{
EVP_CIPHER_CTX ctx;
intaddLen=0, orgLen=0;
unsigned long err=0;
ERR_load_crypto_strings();
EVP_CIPHER_CTX_init(&ctx);

if (EVP_EncryptInit(&ctx, EVP_aes_128_ecb(), key, NULL) != 1) {
err = ERR_get_error();
printf("ERR: EVP_EncryptInit() - %s\n", ERR_error_string (err, NULL));

return -1;
}

if (EVP_EncryptUpdate(&ctx, cipherText, &orgLen, plainText, plainTextLen) != 1) {
err = ERR_get_error();
printf("ERR: EVP_EncryptUpdate() - %s\n", ERR_error_string (err, NULL));
return -1;
}
if (EVP_EncryptFinal(&ctx, cipherText+orgLen, &addLen) != 1) {
err = ERR_get_error();
printf("ERR: EVP_EncryptFinal() - %s\n", ERR_error_string (err, NULL));

return -1;
}

EVP_CIPHER_CTX_cleanup(ctx);
ERR_free_strings();

returnaddLen + orgLen;
}

복호화

#include <openssl/evp.h
#include <openssl/err.h
#include <openssl/ssl.h
/* AES Decrypt Process */
intdecrypt_block(unsigned char* plainText, unsigned char* cipherText, unsigned intcipherTextLen, unsigned char* key)
{
EVP_CIPHER_CTX ctx;
unsigned long err=0;
inttoLen=0, outLen=0;
int ret=0;
ERR_load_crypto_strings();
EVP_CIPHER_CTX_init(&ctx);
if (EVP_DecryptInit(&ctx, EVP_aes_128_ecb(), key, NULL) != 1) {
err = ERR_get_error();
printf("ERR: EVP_DecryptInit() - %s\n", ERR_error_string (err, NULL));

return -1;
}

if (EVP_DecryptUpdate(&ctx, plainText, &toLen, cipherText, cipherTextLen) != 1) {
err = ERR_get_error();
printf("ERR: EVP_DecryptUpdate() - %s\n", ERR_error_string (err, NULL));
return -1;
}
if (EVP_DecryptFinal(&ctx, &plainText[cipherTextLen], &outLen) != 1) {
err = ERR_get_error();
printf("ERR: EVP_DecryptFinal() - %s\n", ERR_error_string (err, NULL));
return -1;
}
EVP_CIPHER_CTX_cleanup(&ctx);
ERR_free_strings();
return toLen+outLen;
}

1.2AES(open ssl)

암호화프로그래밍
- 아래는입력받은plain text를암호화키를이용하여cipher text로변환하는함수이다.
- AES_set_encrypt_key()로암호화키를AES_KEY구조체로변환한후암호화를수행한다.

#include <openssl/aes.h
/* AES Encrypt Process */
boolencrypt_block(unsigned char* cipherText, unsigned char* plainText, unsigned char* key)
{
AES_KEY encKey;
if (AES_set_encrypt_key(key, 128, &encKey) < 0)
return false;
AES_encrypt(plainText, cipherText, &encKey);
return true;
}

- 아래는입력받은cipher text를복호화키를이용하여plain text로변환하는함수이다.
- AES_set_decrypt_key()로암호화키를AES_KEY구조체로변환한후복호화를수행한다.

#include <openssl/aes.h
/* AES Decrypt Process */
booldecrypt_block(unsigned char* cipherText, unsigned char* plainText, unsigned char* key)
{
AES_KEY decKey;
if (AES_set_decrypt_key(key, 128, &decKey) < 0)
return false;
AES_decrypt(cipherText, plainText, &decKey);
return true;
}

- 다음은ase.h에정의된aes암호화함수이다. (ecb, ebc암호화모드등을지원한다.)

void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, constintenc);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, constintenc);
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, int *num, constintenc);
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, int *num, constintenc);
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, int *num, constintenc);
void AES_cfbr_encrypt_block(const unsigned char *in,unsigned char *out,
constintnbits,const AES_KEY *key,
unsigned char *ivec,constintenc);
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, int *num);
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num)

2RSA

- RSA구조체

struct{
BIGNUM *n; // public modulus
BIGNUM *e; // public exponent
BIGNUM *d; // private exponent
BIGNUM *p; // secret prime factor
BIGNUM *q; // secret prime factor
BIGNUM *dmp1; // d mod (p-1)
BIGNUM *dmq1; // d mod (q-1)
BIGNUM *iqmp; // q^-1 mod p
// ...
} RSA;

RSA구조체는BIGNUM components로 구성되어 있으며, public key와private key모두를 가지고 있다.

-주요 함수 프로토 타입

#include <openssl/rsa.h
#include <openssl/engine.h
//객체 생성,삭제
RSA * RSA_new(void);
void RSA_free(RSA *rsa);
// RSA암,복호화
intRSA_public_encrypt(intflen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
intRSA_private_decrypt(intflen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
intRSA_private_encrypt(intflen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
intRSA_public_decrypt(intflen, unsigned char *from, unsigned char *to, RSA *rsa,int padding);
// RSA서명 및 검증
intRSA_sign(int type, unsigned char *m, unsigned intm_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa);
intRSA_verify(int type, unsigned char *m, unsigned intm_len, unsigned char *sigbuf, unsigned intsiglen, RSA *rsa);
intRSA_size(const RSA *rsa);
// RSA키 생성 및 검사
RSA *RSA_generate_key(intnum, unsigned long e, void (*callback)(int,int,void *), void *cb_arg);
intRSA_check_key(RSA *rsa);
intRSA_blinding_on(RSA *rsa, BN_CTX *ctx);
void RSA_blinding_off(RSA *rsa);
void RSA_set_default_method(const RSA_METHOD *meth);
const RSA_METHOD *RSA_get_default_method(void);
intRSA_set_method(RSA *rsa, const RSA_METHOD *meth);
const RSA_METHOD *RSA_get_method(const RSA *rsa);
RSA_METHOD *RSA_PKCS1_SSLeay(void);
RSA_METHOD *RSA_null_method(void);
intRSA_flags(const RSA *rsa);
RSA *RSA_new_method(ENGINE *engine);
// RSA context출력
intRSA_print(BIO *bp, RSA *x, int offset);
intRSA_print_fp(FILE *fp, RSA *x, int offset);
intRSA_get_ex_new_index(long argl, char *argp, int (*new_func)(), int (*dup_func)(), void (*free_func)());
intRSA_set_ex_data(RSA *r,intidx,char *arg);
char *RSA_get_ex_data(RSA *r, intidx);
int RSA_sign_ASN1_OCTET_STRING(int dummy, unsigned char *m, unsigned intm_len, unsigned char *sigret,unsigned int *siglen, RSA *rsa);
int RSA_verify_ASN1_OCTET_STRING(int dummy, unsigned char *m, unsigned intm_len, unsigned char *sigbuf,unsigned intsiglen, RSA *rsa);

( 찾아 볼 수 있다.)

테스트 프로그램

- RSA알고리즘을 활용하여 간단한 테스트 프로그램을 작성해 보자.

-아래 코드는 텍스트를 암,복호화 하는 코드이다.

#include <stdio.h
#include <stdlib.h
#include <string.h
#include <openssl/rsa.h
#include <openssl/evp.h
int main(intargc, char *argv[])
{
RSA *rsa;
intlen, ret;
unsigned char *cipherText;
unsigned char *plainText = "Hello RSA!";
unsigned char *originText;
rsa = RSA_generate_key(1024, 3, NULL, NULL);
if (RSA_check_key(rsa) != 1)
{
perror("not gnerate RSA key");
exit(0);
}
cipherText = (unsigned char *) calloc (1, (size_t) RSA_size(rsa));
len = RSA_public_encrypt(strlen(plainText), plainText, cipherText, rsa, RSA_PKCS1_PADDING);
if (len == -1)
{
perror("not encrypt data");
exit(0);
}
printf("plain text: %s\n", plainText);
printf("ciper text: %s\n", cipherText);
originText = (unsigned char *) calloc(1, strlen(plainText)+1);
ret = RSA_private_decrypt(len, cipherText, originText, rsa, RSA_PKCS1_PADDING);
if (ret == -1)
{
perror("not decrypt data");
exit(0);
}
printf("origin text: %s\n", originText);
free(cipherText);
free(originText);
RSA_free(rsa);
return 0;
}

3SHA1

다음 함수 추가.

#include "sha1.h"

int SHA1_String(const char* src, intsrc_len, char* dst, intdst_len)

{

SHA1Context sha1;

int err;

unsigned char result[20];

chartmp[41];

err = SHA1Reset(&sha1);

if(err != shaSuccess) return err;

err = SHA1Input(&sha1, (const unsigned char *)src, src_len);

if(err != shaSuccess) return err;

err = SHA1Result(&sha1, result);

if(err != shaSuccess) return err;

for (inti=0; i<20; i++)

sprintf(tmp+i*2, "%02X", result[i]);

strncpy(dst, tmp, dst_len);

returnshaSuccess;

}

예를 들어, "GRAK" 이라는 문자열을 넣는다면, 다음과 같은 값이 나온다.

F8BE3699704F2E49F8D30C64FCCE3B3E10F887A8

< 값 비교 및 사용예제 >

char s[256];

char t[256];

gets(s);

SHA1_String(s, strlen(s), t, 256);

if(strcmp(t, "F8BE3699704F2E49F8D30C64FCCE3B3E10F887A8") != 0)

{

puts("암호 틀렸다 엑세스 거부");

return -1;

}

// 정상실행

4SHA2-256

public String testSHA256(String str){

String SHA = "";

try{

MessageDigestsh = MessageDigest.getInstance("SHA-256");

sh.update(str.getBytes());

bytebyteData[] = sh.digest();

StringBuffersb = new StringBuffer();

for(inti = 0 ; ibyteData.length ; i++){

sb.append(Integer.toString((byteData[i]&0xff) + 0x100, 16).substring(1));

}

SHA = sb.toString();

}catch(NoSuchAlgorithmException e){

e.printStackTrace();

SHA = null;

}

return SHA;

}

5SHA3-256

<설치>

mkdir sha3

cd sha3

git clone

cd python-sha3

python setup.py build

python setup.py install

<사용예제>

python

from sha3 import sha256

s=sha256()

s.update("")

s.hexdigest()