3개의 알고리즘이 있지만
하나만 사용법 위주로..설명 하도록 하겠다.
사실 알고리즘의 내부에 대해서 잘 알지도 못 할 뿐더러..ㅡ.ㅡ;
내부의 소스 마저도 배포 한것의 C#으로의 컨버전만 한 것 뿐이라..
마땅히 설명하고 말 것도 없다.
주석에도 있지만..
SEED 알고리즘의 경우 아마도..C로 되어 있는것을 서아름님이 컨버전한것을 내가 다시 복사 해온것이다.
빌드 히스토리에 이름 남긴것으로 용서가 될려나..ㅡ.ㅡ;
그리고 ARIA 알고리즘의 경우에는 JAVA 코드를 내가 C#으로 컨버전 한것이다.
AriaTest라는 클래스는 알고리즘을 배포 할때 테스트 하기 위해 같이 배포한 예제를 C#으로 컨버전 한것이다.
일단은 이 컨버전 한 결과치와 원본의 결과치가 같으므로
이 알고리즘은 정상적으로 구현되었다고 간주(??) 한다.
SEED와 ARIA는 둘다 똑같이 블럭 암호화이다.
블럭 암호화라는 것은 일정 부분(블럭)만 추출 해서 암호화 한다는 얘기가 되겠다.
SEED는 살펴 보건데 16바이트 블럭 암호화만 구현이 된듯 하다.
ARIA 또한 16바이트 블럭 암호화가 구현 되었다.
틀리다고 태글 걸기 없기..ㅡ.ㅡ;
다시 말하지만 암호화 알고리즘에 대해 나도 무지하다..@.@
블럭 암호화이기 때문에 16바이트 이상의 텍스트를 암호화 하기 위해서는 16바이트로 쪼개야 한다.
그리고 남는 부분은 Aria 코드의 경우에는 빈 공간으로 채웠다.
그리고 각각 암호화 한후에 분리된 byte[]을 하나의 byte[]로 붙였다..
복호화 할 때도 이와 같은 방식을 따랐다..
하나씩 조금씩..추적해 보다 보면 알게 될것이다.
각각의 암호화알고리즘은 ~Provider라는 클래스로 접근한다.
다른 클래스로는 접근 할 수 없다.
이제 생성자 부터 알아 보도록 하겠다.
[
소스코드]
/// <summary>
/// 기본 키 사이즈는 128비트
/// </summary>
public AriaProvider()
{
this.keySize = 128;
this.aria = new AriaAlgorithm(this.keySize);
}
/// <summary>
/// 기본 키사이즈는 128
/// </summary>
/// <param name="keySize">128, 192, 256만 지원</param>
public AriaProvider(int keySize)
{
this.keySize = keySize;
this.aria = new AriaAlgorithm(this.keySize);
}
|
생성자를 보게 되면
기본 생성자의 경우 keySize라는 것을 128로 고정 시키고
파라메터를 1개 받는 경우 keySize를 받는다.
keySize라 함은
암호화를 하기 위해 필요한 공용키(Public Key 혹은 Masker Key)를 말한다.(종종 두 단어를 섞어서 쓴다.착오 없도록..ㅡ.ㅡ;)
Aria 알고리즘의 경우 3종류의 공용키를 생성 할 수 있다.
Seed의 경우도 그러리라고 추측은 되지만 구현되어 있는 것은 128비트의 공용키만 지원 하는 것으로 보인다.
지금 설명한 공용키를 받는 프라퍼티를 보도록 하겠다.
[
소스코드]
/// <summary>
/// 암복호화에 이용할 마스터 키
/// 키사이즈에 따라 달라짐(키사이즈:마스터키.Length)
/// (128:16, 192:24, 256:32)
/// </summary>
public byte[] MasterKey
{
get { return masterKey; }
set
{
switch (this.keySize)
{
case 128:
if (value.Length != 16)
{
throw new ArgumentException("MasterKey's Length : " + value.Length.ToString());
}
else
{
this.masterKey = value;
}
break;
case 192:
if (value.Length != 24)
{
throw new ArgumentException("MasterKey's Length : " + value.Length.ToString());
}
else
{
this.masterKey = value;
}
break;
case 256:
if (value.Length != 32)
{
throw new ArgumentException("MasterKey's Length : " + value.Length.ToString());
}
else
{
this.masterKey = value;
}
break;
}
}
}
|
소스를 살펴 보면 알겠지만
생성자에 선언된 keySize에 따라 MasterKey의 사이즈가 정해진다.
이것이 맞지 않으면 예외를 던진다.
마스터키는 byte[] 형으로 이루어지며
생성자 다음에 이를 할당 해주지 않는다면
SetDefaultMasterKey() 메소드에서 정의된 마스터 키를 이용 하게 된다.
정의된 마스터 키는 아래와 같다.
[
소스코드]
/// <summary>
/// 마스터키의 기본값을 정의 한다.
/// </summary>
private void SetDefaultMasterKey()
{
if (this.masterKey == null)
{
int length = (this.keySize == 128) ? 16 : ((this.keySize == 192) ? 24 : 32);
this.masterKey = new byte[length];
for (int i = 0; i < length; i++)
{
this.masterKey[i] = (byte)i;
}
}
}
|
만약에 마스터 키를 생성하여 사용하고자 한다면
다음과 같이 하면 되겠다.
[
소스코드]
//선언
internal class AriaKey
{
internal static byte[] PublicKey = { 42, 52, 64, 1, 0, 135, 123, 75, 34, 12, 43, 74, 36, 28, 92, 16 };
}
//사용
AriaProvider aria = new AriaProvider();
aria.MasterKey = AriaKey.PublicKey;
|
이제 암호화 하는 부분을 알아 보겠다.
실제로 접근이 가능한(public) 메소드는 암호화 메소드 2개와 복호화 메소드 2개가 있다.
먼저 암호화 메소드에 대해서 알아 보겠다.
암호화 메소드는 2개가 있는데 너무나 Clear 하다.
하나는 문자열을 받아 암호화 하여 문자열로 리턴 하고 또 하나는 문자열을 받아 byte[]로 리턴 한다.
문자열을 리턴 하는 방식은 - byte[]을 string으로 변환 하는 방식- 여러 가지가 있으나
나는 BitConverter를 이용한 방법으로 했다.
이에 토를 달지 말것..ㅡ.ㅡ;
[
소스코드]
/// <summary>
/// 문자열을 받아 암호화된 문자열을 반환한다.
/// </summary>
/// <param name="inputText">암호화할 문자열입니다.</param>
/// <returns>암호화된 문자열입니다.</returns>
public string EncryptToString(string inputString)
{
if (String.IsNullOrEmpty(inputString))
{
return inputString;
}
else
{
this.Encrypt(inputString);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < this.cipherTextBlock.Length; i++)
{
sb.Append(BitConverter.ToString(this.cipherTextBlock[i]).Replace("-", ""));
}
return sb.ToString();
}
}
/// <summary>
/// 문자열을 받아 암호화된 byte[]을 반환한다.
/// </summary>
/// <param name="inputText">암호화할 문자열입니다.</param>
/// <returns>암호화된 byte[]입니다.</returns>
public byte[] EncryptToByteArray(string inputString)
{
if (String.IsNullOrEmpty(inputString))
{
return null;
}
else
{
this.Encrypt(inputString);
byte[] retValue = new byte[this.cipherTextBlock.Length * 16];
for (int i = 0, j = 0; i < this.cipherTextBlock.Length; i++, j += 16)
{
Buffer.BlockCopy(this.cipherTextBlock[i], 0, retValue, j, 16);
}
return retValue;
}
|
복호화 하는 부분은 암호화와 똑같이 2개의 메소드로 이루어 졌으며 방식 또한 똑같다.
[
소스코드]
/// <summary>
/// 암호화된 문자열을 받아 복호화한다.
/// </summary>
/// <param name="inputText">암호화된 문자열입니다.</param>
/// <returns>복호화된 문자열입니다.</returns>
public string DecryptFromString(string inputString)
{
if (String.IsNullOrEmpty(inputString))
{
return inputString;
}
else
{
this.Decrypt(inputString);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < this.plainTextBlock.Length; i++)
{
sb.Append(Encoding.Default.GetString(this.plainTextBlock[i]));
}
return sb.ToString().Trim();
}
}
/// <summary>
/// 암호화된 byte[]을 받아 복호화한다.
/// </summary>
/// <param name="inputByteArray">암호화된 byte[]입니다.</param>
/// <returns>복호화된 문자열입니다.</returns>
public string DecryptFromByteArray(byte[] inputByteArray)
{
if (inputByteArray == null || inputByteArray.Length == 0)
{
return String.Empty;
}
else
{
this.Decrypt(inputByteArray);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < this.plainTextBlock.Length; i++)
{
sb.Append(Encoding.Default.GetString(this.plainTextBlock[i]));
}
return sb.ToString().Trim();
}
}
|
알고리즘을 개발 해 내는 것은 학자들의 몫이다.
이를 코드로 개발해 내고 또 프로그램에 적용 하고 사용 하는 것은 개발자의 몫이다..
나 또한 개발자로서 알고리즘 정의서만 보고 이정도의 코드를 짜내면..좋겠지만..ㅡ.ㅡ;
실력의 미흡함과..부족한 IQ로 인해..@.@
단지 내가 써먹기 편하게끔 변형 시키는게 한계일 것 같다..ㅡ.ㅠ;
공공기관의 프로젝트를 하기 위해서는
필히..위 알고리즘(SEED와 ARIA)중에 하나를 이용해야 한다.
다른건 안된다..ㅡ.ㅡ;
왜냐..국정원에서 그렇게 하라고 시키기 때문이다..
쿨럭~~~
암튼
위 알고리즘의 사용에 있어 잘못된 암호화 또는 버그가 있다면 언제든지 Call해주기 바란다??
※
구현환경
.NET Framework 2.0
Microsoft Visual Studio.NET 2005
Microsoft Windows XP SP2