상세 컨텐츠

본문 제목

[PHP] 시드 암호화 알고리즘(KISA SEED Encryption algorithm)

Programing/PHP

by 호짱 HoZang 2019. 8. 17. 01:17

본문

한국인터넷 진흥원 시드 암호화 알고리즘

KISA SEED Encryption algorithm

KISA SEED 암호화 알고리즘

프로젝트를 진행하던 중 타 회사에서 개발중인 시스템과 정보를 공유해야할 일이 있었는데,

그 때 KISA SEED 암호화 알고리즘을 사용하게되었던 경험을 정리했습니다.

암호화 알고리즘 소스와 개발 매뉴얼 다운로드 페이지입니다.

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

 

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

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

seed.kisa.or.kr

링크에 암호화 알고리즘 소스 다운로드 페이지로 가서 다운로드 받으셨나요?

언어별로, 운영모드(CBC, CTR, GCM 등) 별로 소스코드가 있습니다.

그러면 그냥 다운로드 받은 소스코드의 함수를 실행하면되지 뭐 때문에 이 글을 적는가?

아마 다운로드한 소스코드의 encrypt, decrypt 함수를 실행하면 암호화, 복호화가 정상적으로 안될겁니다.

예전이 이 소스코드 실행하다가 맨붕했던 기억나네요... ... 그래서 이렇게 사용방법을 공유해봅니다.

참고로 예제로 보여드릴 코드는 CBC운영모드를 기준으로 했습니다.

우선 다운로드 받은 소스코드의 함수를 실행하면 정상 작동안하는 이유는 SEED 암호화 알고리즘은 128비트 블록 암호화 알고리즘입니다.

위 링크에 같이 첨부된 개발 메뉴얼 PDF파일을 읽어보면

SEED 암호화 알고리즘 개발 메뉴얼 중

암호화할 데이터를 128비트 단위로 블럭화 해야합니다.

그러니까 마지막 블럭의 크기가 128비트가 안되면 나머지 크기만큼 패딩을 해서 128비트 블럭을 만들라는 말이겠죠?

그래서 개발 매뉴얼 PDF 내용중 고려사항에서 좀 더 뒤로 가면 패딩방법 3가지를 설명하주고 있습니다.

직접 패딩하란 소리죠. ㅎ ㅏㅎ ㅏㅎ ㅏ 하긴 암호화 알고리즘 만들어 준게어디야... 라고 작업 당시에 생각했는데

최근에 Java로 작업하게 되서 Java 소스를 살펴보니 패딩처리까지 되어있더군요.

나머지 다른 언어들은 확인하지 못했지만 정말 치사하단 생각이 들더라구요. ㅜ_ㅡ 지못미 PHP

 

어쨋든 PDF에 패딩이 필요하다니까 해야하겠죠. 그런데 내용이 좀...

SEED 암호화 알고리즘 블럭 패딩 설명

그냥 작성된 소스코드 좀 주시면 안될까요? 하...

그래서 구글링을 해서 패딩작업을 한 소스를 찾았습니다.

참고한 소스의 출처를 적으려니 너무 오래되서 어디서 참고했는지 기억이 잘 안나네요.

죄송하지만 출처를 좀 생략하고 다른 곳에서 참고했다는 것만 밝히겠습니다.

<?php
require_once ('KISA_SEED_CBC.php');

class KISA_SEED_CBC_HANDLE
{
	private static $g_bszUser_key = [ "f1", "96", "ff", "18", "28", "c8", "ef", "cc", "ab", "1a", "fd", "8d", "8c", "b9", "a4", "34" ];
	private static $g_bszIV = [ "78", "69", "81", "ab", "4a", "4c", "2c", "a8", "a9", "99", "67", "81", "77", "a1", "cc", "bb" ];
	private static $SeedBlockSize = 16;
	private static $PADDING_VALUE = 0x0F;

	public function addPadding($source, $blockSize) {
		$paddingResult = $source;
		$paddingCount = $blockSize - (count($source) % $blockSize);
		if (!$paddingCount) {
			for($i=0;$i<self::$SeedBlockSize;$i++) {
				$paddingResult[] = self::$PADDING_VALUE;
			}
		} else {
			for($i=0;$i<$paddingCount;$i++) {
				$paddingResult[] = 0x0A;
			}
		}

		return $paddingResult;
	}

	public function removePadding($source, $blockSize) {
		$paddingResult = $source;
		$byte_length = count($source);
		$lb_start = $byte_length - $blockSize - 1;
		$is_padding = false;
		$padding_start = 0;
		for ($i = $lb_start; $i < $byte_length; $i++) { 
			if ($source[$i] == 10) {
				$is_padding = true;
				$padding_start = $i;
				break;
			}
		}
		for ($i = $padding_start; $i < $byte_length; $i++) {
			array_pop($paddingResult);
		}

		return $paddingResult;
	}

	public function encrypt($str) {

		$planBytes = array_slice(unpack('c*', $str), 0);
		$planBytes = $this->addPadding($planBytes, self::$SeedBlockSize);
		$keyBytes = self::$g_bszUser_key;
		$IVBytes = self::$g_bszIV;
		
		for($i = 0; $i < 16; $i++)
		{
			$keyBytes[$i] = hexdec($keyBytes[$i]);
			$IVBytes[$i] = hexdec($IVBytes[$i]);
		}

		if (count($planBytes) == 0) {
			return $str;
		}
		$ret = null;
		$bszChiperText = null;
		$pdwRoundKey = array_pad(array(),32,0);

		$bszChiperText = KISA_SEED_CBC::SEED_CBC_Encrypt($keyBytes, $IVBytes, $planBytes, 0, count($planBytes));

		$r = count($bszChiperText);

		for($i=0;$i< $r;$i++) {
			$ret.= ($ret ? "," : "") . sprintf("%02X", $bszChiperText[$i]);
		}
		return $ret;
	}

	public function decrypt($str) {
		$planBytes = [];
		$keyBytes = self::$g_bszUser_key;
		$IVBytes = self::$g_bszIV;
		
		for($i = 0; $i < 16; $i++)
		{
			$keyBytes[$i] = hexdec($keyBytes[$i]);
			$IVBytes[$i] = hexdec($IVBytes[$i]);
		}

		$hex_arr = explode(",", $str);

		foreach ($hex_arr as $hex) {
			$dec = hexdec($hex);
			$planBytes[] = $dec;
		}

		if (count($planBytes) == 0) {
			return $str;
		}

		$pdwRoundKey = array_pad(array(),32,0);

		$bszPlainText = null;

		$planBytresMessage = "";
		$bszPlainText = KISA_SEED_CBC::SEED_CBC_Decrypt($keyBytes, $IVBytes, $planBytes, 0, count($planBytes));
		for($i=0;$i< sizeof($bszPlainText);$i++) {
			$planBytresMessage .=  sprintf("%02X", hexdec($bszPlainText[$i])).",";
		}

		$decryptHexStr = substr($planBytresMessage,0,strlen($planBytresMessage)-1);
		$decryptHex = explode(",", $decryptHexStr);

		$dec_data = call_user_func_array("pack", array_merge(array("c*"), $decryptHex));
		return $dec_data ? trim($dec_data) : "";
	}

}

끝으로 클래스 속성값으로 선언해준 암호화 seed 값은 원하는 16진수 값으로 넣으시면 됩니다.

관련글 더보기

댓글 영역