What is Cryptography?

암호화란 데이터를 보호 하는데 사용되며 그 외에도 유용하게 많은 곳에서 사용된다.
이는 데이터가 보여지고, 수정되어지는 것을 방지하고, 생성자의 데이터에 대한 무결성을 보장하기 위해 사용되어진다.
암호화는 데이터를 암호화 하여 암호화 된 상태에서 네트워크 상에 전송하며 그리고 수신측에서 다시 데이터를 암호 해독함으로써, 인터넷과 같은 안전하지 않은 네트워크 상에서 보안 통신을 제공하는 메커니즘을 제공한다.
Encryption은 데이터베이스에 저장된 암호와 같은 정보를 사람이 읽을수 있고 이해할 수 있게 하는 것을 방지하는 추가적인 보안 메커니즘에 이용되어 질수 있다.

Encryption Component
인크립션은 데이터를 암호화하고 해독하는 키와 조합된 암호화 알고리즘의 사용을 포함한다.
모든 암호화 알고리즘의 목적은 적절한 키 없이는 데이터를 암호해독 하는 것을 가급적 어렵게 만드는데 있다.
Microsoft .NET 프레임워크 클래스(System.Security.Cryptography)는 암호화에 대한 상세정보를 관리해 줄것이다.
이 클래스들은 동일한 인터페이스로 구현된다. ; 그래서 이 클래스들을 가지고 작업하는 것은 Cryptography 네임스페이스를 통해 하는 것과 동일하다.
프레임워크내의 어떤 클래스들은 단지 Microsoft CryptoAPI에 존재하는 알고리즘에 대한 래퍼이다. 다른 클래스들은 그 주요한 알고리즘에 대한 구현을 관리한다.

Public-Key Encryption
비대칭 암호화를 알려진 공개키 암호화는 공개키와 비밀키 쌍을 이용하여 데이터를 암호화하고 암호해독한다.
공개키는 누구나 사용할 수 있도록 되어있으며, 비밀키 소유자에게 보내질 데이터를 암호화 하는데 사용된다.
비밀키는 그 이름이 의미하듯 기밀을 유지한다. 비밀키는 데이터를 암호해독하는데 사용되며 오직 정확한 공개키가 데이터 암호화에 사용된 경우에만 작동하게 된다.
비밀키는 공개키로 암호화된 데이터를 암호해독 하는데 사용될수 있는 유일한 키이다.
키들은 여러 번 사용될수 있게 저장될수 있으며 또는 한번만 사용되기 위해 생성 될수도 있다.

비대칭 암호화 알고리즘은 대게 단지 적은 양의 데이터를 암호화하는데 효율적이다.
아래의 공개키 알고리즘은 .NET Framework 상에서 사용될 수 있다.

- Digital Signature Algorithm(DSA)
- RSA

Private-Key Encryption
대칭 암호화로 알려진 비밀키 암호화는 정보를 암호화하고 암호해독하는데 하나의 키를 이용한다. 키는 인증되지 않은 자에 의해 데이터가 암호해독되어 데이터가 손상되지 않도록 기밀을 유지해야 하며. 비밀키 알고리즘은 상대적으로 빠르며 거대한 데이터 스트림을 암호화하고 암호해독하는데 사용될수 있다.
비밀키 알고리즘은 block ciphers로 알려져 있다. 왜냐하면, 이 알고리즘은 데이터를 한번에 한 블록씩 암호화하기 때문이다.
Block ciphers는 알고리즘과 키에 기반하여 동일한 입력블럭을 동일한 출력블럭으로 암호화한다. 만일 데이터의 구조를 누군가 알고 있다면, 패턴이 인식되어 키가 역공학되어 질수 있는 가능성이 있다. 이를 해결하기 위해, .NET Framework 상의 클래스들은 Chaining이라 알려진 처리를 이용한다. 이는 이전 블록의 정보가 현재 블록을 암호화하는데 사용되도록 한다. 이는 키가 발견되지 않도록 방지한다. 이는 첫 블록의 데이터를 암호화 하는데 초기화 백터(Initialization vector : IV)를 요구한다.

아래의 비밀키 알고리즘은 .NET Framework 상에서 이용가능한 것이다. 각각의 상세내용에는 각 알고리즘에 대한 기본적인 정보를 담고 있으며 장, 단점을 포함하고 있다.

- Data Encryption Standard(DES) 알고리즘은 데이터를 64 bit 블록으로 암호화하고 해독하는데 64bit 키를 이용한다. 키가 64bit라 할지라도 효율적인 키 강도는 단지 56 bit이다. 적당한 시간안에 모든 DES 키를 검색할수 있는 하드웨어 장비가 존재한다. 이것은 DES 알고리즘이 깨어질수 있게 하였고, 그래서 이 알고리즘은 쓸모없는 것으로 취급되었다.
- RC2는 가변 키 길이 block cipher이다. 키 길이는 8bit에서 64bit로 가변적일 수 있다. 이는 특히 DES보다 안전한 대안으로서 설계되었다. 처리시간은 DES에 비해 2, 3배 빨라졌다. 하지만 .NET Framework 에서 사용가능한 RC2CryptoServiceProvider는 8 문자 또는 64bit 키로 제한되었다. 8문자 제한은 이 알고리즘이 DES가 가졌던 공격위험성을 그대로 가지게 하였다.
- TripleDES 알고리즘은 DES알고리즘의 세가지 계승적인 반복을 사용한다.
- 이 알고리즘은 2개 키, 3개 키를 사용한다. DES알고리즘과 같이 키 길이는 64bit 에 유효 키강도는 56bit이다. TripleDES 알고리즘은 DES 알고리즘의 결점을 정정하기 위해 설계되었다. 그러나 세 반복(Three Iteration)은 처리시간을 DES보다 세배 정보 느리게 하는 결과를 낳았다.
- Advanced Encryption Standard(AES) 알고리즘의 하나인 Rijndeal 알고리즘은 DES 알고리즘의 대안으로서 설계되었다. 키 강도는 DES보다 강하고 DES보다 나은 성능을 위해 설계되었다. 키의 길이는 128, 192, 256 bit로 가변적일수 있다. 이 알고리즘은 가장 신뢰할수 있으며 이번 칼럼 내용의 예제에서 사용하겠다.

Hashing Algorithm
Hashing은 특정 길이의 데이터를 고정 길이 바이트 시퀀스로 맵핑하는 것을 의미한다.
입력이 타이핑 테스트 이거나 법전의 내용이든 상관없이 결과는 동일 크기로 나타날 것이다.
해싱은 독특한 결과를 생산한다. 똑 같은 두개의 눈송이가 존재하지 않듯이 두개의 입력 조합이 동일한 해시 결과를 생산할 수는 없다. 입력이 하나의 문자가 다를지라도 다른 결과를 생산한다. .NET Framework는 아래의 해시 알고리즘에 대한 자원을 제공한다.

- HMACSHAI
- MACTripleDES
- MD5CryptoServiceProvider
- SHA1Managed
- SHA256Managed
- SHA384Managed
- SHA512Managed

How to Generate a Key and IV for Private-key Encryption
각 알고리즘은 사용되는 특정 키 사이즈를 가지고 있다. 각 키는 미리 정의된 크기, 전형적으로 1 문자(8bit) 에서 32문자(256bit)의 범위를 가지는, 에 맞추어야 한다.
어떤 알고리즘은 다양한 키 사이즈를 지원한다. 그러나 특정 알고리즘의 키 사이즈의 유효한 범위 내에 있어야만 한다. 우리는 128, 192, 256 bit key를 지원하는 RiJndeal를 사용할 것이다. 128 bit 키를 만드는 방법은 해싱 알고리즘의 하나를 이용해서 만든다.
아래의 code outline에서 클래스는 입력구를 받아서 키를 생성하고 IV를 생성하는 메서드를 포함한다.


// Initialize internal values
this._Key = new byte[24];
this._IV = new byte[16];

// Perform a hash operation using the phrase. This will generate
// a unique 48 character value to be used as the key and IV.
byte[] bytePhrase = Encoding.ASCII.GetBytes(Phrase);
SHA384Managed sha384 = new SHA384Managed();
sha384.ComputeHash(bytePhrase);
byte[] result = sha384.Hash;

// Transfer the first 24 characters of the hashed value to the key
// and 16 more characters for the initialization vector.
for( int loop=0; loop<24; loop++ ) this._Key[loop] = result[loop];
for( int loop=24; loop<40; loop++ ) this._IV[loop-24] = result[loop];


How to Use Private-Key Encryption
아래의 클래스는 데이터를 암호하 하는데 사용되는 비밀키를 생성하기 위해 해싱을 하는 방법을 데모한다. 암호해독 메서드는 암호화 함수에서 사용된 것의 역 함수를 사용함으로써 간단히 이용될수 있다.


using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

internal class MyEncryptor
{
// Internal value of the phrase used to generate the secret key
private string _Phrase = "";
/// Set the phrase used to generate the secret key.
public override string Phrase
{
set
{
this._Phrase = value;
this.GenerateKey();
}
}

// Internal initialization vector value to
// encrypt/decrypt the first block
private byte[] _IV;

// Internal secret key value
private byte[] _Key;

///
/// Constructor
///

/// Secret phrase to
generate key
public MyEncryptor(string SecretPhrase)
{
this.Phrase = SecretPhrase;
}

///
/// Encrypt the given value with the Rijndael algorithm.
///

/// Value to encrypt
/// Encrypted value.
public string Encrypt(string EncryptValue)
{
CryptoStream encryptStream = null; // Stream used to encrypt
RijndaelManaged rijndael = null; // Rijndael provider
ICryptoTransform rijndaelEncrypt = null; // Encrypting object
MemoryStream memStream = new MemoryStream(); // Stream to contain
// data

try
{
if( EncryptValue.Length > 0 )
{
// Create the crypto objects
rijndael = new RijndaelManaged();
rijndael.Key = this._Key;
rijndael.IV = this._IV;
rijndaelEncrypt = rijndael.CreateEncryptor();
encryptStream = new CryptoStream(
memStream, rijndaelEncrypt, CryptoStreamMode.Write);

// Write the encrypted value into memory
byte[] input = Encoding.UTF8.GetBytes(EncryptValue);
encryptStream.Write(input, 0, input.Length);
encryptStream.FlushFinalBlock();

// Retrieve the encrypted value and return it
return( Convert.ToBase64String(memStream.ToArray()) );
}
else
{
return "";
}
}
finally
{
if( rijndael != null ) rijndael.Clear();
if( rijndaelEncrypt != null ) rijndaelEncrypt.Dispose();
if( memStream != null ) memStream.Close();
}
}

/*****************************************************************
* Generate an encryption key based on the given phrase. The
* phrase is hashed to create a unique 32 character (256-bit)
* value, of which 24 characters (192 bit) are used for the
* key and the remaining 8 are used for the initialization
* vector (IV).
*
* Parameters: SecretPhrase - phrase to generate the key and
* IV from.
*
* Return Val: None
***************************************************************/
private void GenerateKey(string SecretPhrase)
{
// Initialize internal values
this._Key = new byte[24];
this._IV = new byte[16];

// Perform a hash operation using the phrase. This will
// generate a unique 32 character value to be used as the key.
byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);
SHA384Managed sha384 = new SHA384Managed();
sha384.ComputeHash(bytePhrase);
byte[] result = sha384.Hash;

// Transfer the first 24 characters of the hashed value to the key
// and the remaining 8 characters to the intialization vector.
for( int loop=0; loop<24; loop++ ) this._Key[loop] = result[loop];
for( int loop=24; loop<40; loop++ ) this._IV[loop-24] = result[loop];
}
}

+ Recent posts