RPNetworks.Security

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (1/5/2011 11:40:08 AM) Viewing : 5620

오늘 살펴볼 내용은 암호화입니다.

지원하는 암호화 알고리즘은 크게 3가지입니다.

ARIA 알고리즘, SEED 알고리즘, HASH 알고리즘입니다.

그중에 HASH알고리즘은 MD5, SHA1, SHA256 을 지원합니다.

ARIA 알고리즘과 SEED 알고리즘은 우리나라 표준 알고리즘이며 대칭키 기반 블럭암호화 알고리즘입니다.

우리 나라 표준이기에 공공기관의 프로젝트에서는 반드시 이 2개의 암호화 알고리즘중 한개를 선택해서 사용해야 합니다.

그러나 ARIA에 비해 SEED는 속도가 매우 느립니다. 아마도 먼저 확실하진 않지만 개발되었기에 그렇겠죠?

그렇기에 복호화가 가능한 암호화를 하기 위해서는 ARIA 알고리즘을 써야 합니다.

복호화가 불가능한 HASH 알고리즘은 비밀번호나 주민등록번호 처럼 복호화가 불가능한 데이터에 사용되어 지죠.

MSDN에 의하면 MD5보다는 SHA1이 보안이 강화되었으며 SHA1 보다는 SHA256이 보안이 더 강화되었읍니다.

이미 MD5는 수십년전에 깨진 암호화 알고리즘이며 SHA1 또한 십수년 전에 깨진 알고리즘입니다.

알아서 잘 선택하기 바랍니다.

이제 다시 코드로 돌아 와서 ...지원하는 타입은 아래와 같습니다.

/// 
/// 암호화 타입 Ver 1.0
/// 
/// 
/// 2008.07.08 - ProtoType - 이방은(www.bangsil.net)
/// 
public enum SecurityType
{
    /// 
    /// 아리아 알고리즘입니다.
    /// 
    AriaAlgorithm = 0,
    /// 
    /// 시드 알고리즘입니다.
    /// 
    SeedAlgorithm,
    /// 
    /// 128비트 MD5 알고리즘입니다.
    /// 
    MD5,
    /// 
    /// 128비트 SHA1 알고리즘입니다.
    /// 
    SHA1,
    /// 
    /// 256비트 SHA256 알고리즘입니다.
    /// 
    SHA256
}

암호화를 하기 위해서는 SecuirtyProviderBase 라는 팩토리 클래스를 이용합니다.

각 암호화 클래스의 인스턴스는 이 팩토리 클래스의 CreateInstance 메서드를 통해서만 얻을 수 있습니다.

public static SecurityProviderBase CreateInstance(SecurityType sType, int keySize)
{
    if (sType == SecurityType.AriaAlgorithm)
    {
        if (keySize != 128 && keySize != 192 && keySize != 256)
        {
            throw new ArgumentOutOfRangeException(string.Format
(CommonLocalizedEnumConverter.ConvertToString(ExceptionMessage.OutOfRange)
, keySize.ToString()));
        }
    }
    switch (sType)
    {
        case SecurityType.AriaAlgorithm:
            SecurityProviderBase p = new AriaProvider(keySize);
            p.keySize = keySize;
            return p;
        case SecurityType.SeedAlgorithm:
            return new SeedProvider();
        case SecurityType.MD5:
            return new HashProvider(SecurityType.MD5);
        case SecurityType.SHA1:
            return new HashProvider(SecurityType.SHA1);
        case SecurityType.SHA256:
            return new HashProvider(SecurityType.SHA256);
        default:
            return null;
    }
}

ARIA 알고리즘을 제외하고는 keySize가 필요치 않습니다. 이에 keySize가 없는 메서드도 overload 되어 있습니다.

ARIA 알고리즘은 블럭암호화 알고리즘이며 MASTER KEY 라는 것이 필요합니다. 이 키값은 매우 중요한 값이며 키값이 노출되면 복호화가 가능하게 됩니다.

어쨋든 이 키값을 생성하기 위한 메서드는 CreateMasterKey 라는 메서드입니다.  입력받은 문자열을 인코딩하여 키값을 생성합니다.

이 메서드를 호출하지 않으면 임의로 마스터키를 생성합니다만 직접 생성하기를 권합니다.

이제 암호화 복호화 메서드가 존재합니다.

이 메서드는 각각 2개씩 존재합니다. 인풋 매개변수의 형식 및 리턴 형식이 String 인 메서드와 byte[]  인 메서드가 존재합니다.

 public string EncryptToString(string inputString) 와 public byte[] EncryptToByteArray(string inputString) 은 암호화 메서드가 되겠고
public string DecryptFromString(string inputString) 와 public string DecryptFromByteArray(byte[] inputByteArray) 는 복호화 메서드가 되겠습니다

각각 상황에 맞게 사용하면 되겠네요.

사용법은 너무나 간단합니다.

SecurityProviderBase security=  SecurityProviderBase.CreateInstance(SecurityType.AriaAlgorithm, 128);
security.CreateMasterKey("마스터키");//생략 하면 기본 설정됨.
string 암호화된문자열 = security.EncryptToString("암호화할 문자열");

 

PS : 삽질전문개발자 님 감사합니다.


마지막 업데이트 : (6/14/2011 7:10:02 PM)




첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (6)
삽질전문개발자님의 글 (6/13/2011 11:07:28 PM)
분문 중 "ARIA 알고리즘과 SEED 알고리즘은 우리나라 표준 알고리즘이며 공개키 기반 블럭암호화 알고리즘입니다."

ARIA와 SEED는 대칭키(비밀키) 블럭 암호화 알고리즘이며, 공개키 기반 암호화라 함은 비밀키/공개키의 키 쌍을 갖는 암호화 방법을 뜻합니다. 즉, 본문의 표현을 인용하여 이야기하면 '마스터키' 방식의 암호화는 공개키 기반 암호화 알고리즘일 수 없습니다.

* 기술 블로그의 부정확한 내용은 후학들과 대중에게 불량 씨앗을 나눠주는 것과 같습니다. 본문을 정정하시면 이 댓글은 삭제하셔도 무방합니다



방실이님의 글 (6/14/2011 7:08:17 PM)
대칭키이군요..^^; 감사합니다.



이세기님의 글 (9/26/2011 8:13:50 PM)
정말 난감했는데 많은 도움이 되었습니다 감사합니다.



방실이님의 글 (9/27/2011 2:18:05 PM)
감사합니다..^^



고은애님의 글 (8/8/2012 2:01:21 PM)
감사합니다^^



김성수님의 글 (7/16/2013 10:23:04 PM)
좋은 공부가 되었습니다. 감사합니다.



댓글 쓰기

RPNetworks.Core - SqlDB 클래스

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (12/1/2010 8:23:33 PM) Viewing : 1822

첨부 파일은 템플릿으로 제공됩니다.

템플릿에 대한 설명은 예전 게시글 중 댓글을 참고 하시면 되겠습니다.

예전 버전에 비해 업데이트가 좀 있었습니다.

가장 큰 이슈는 연결 문자열의 암호화를 느슨한 연결로 변경한 부분이 되겠습니다.

그리고 주석도 좀 보강을 했지요.

먼저 생성자 부분을 보겠습니다.

/// 
///   클래스의 생성자입니다. 기본값은 암호화를 사용하지 않습니다.
/// 
/// Config파일에서 정의된 connectionString의 name 값입니다
/// config 파일에 다음과 같이 정의되어 있어야 합니다.
/// 
///   
///    
///     
///      
///      
///     
///    
///   
///  
/// 생성자는 다음과 같이 호출 됩니다.
/// 
/// SqlDB db = new SqlDB("con");
/// 
/// 
public SqlDB(string connectionString)
{
    this.connection = new SqlConnection(ConfigurationHelper.GetConnectionString(connectionString));
}

xml 주석으로 도움말 파일을 생성하게 되면 위와 같은 주석이 도움말에 포함이 되죠.. http://bangsil.net/Tag/주석 을 참고 하십시요.

cinfig 설정에 대한 부분은 추후 Cofiguration 파트에서 다시 설명하도록 하겠습니다.

위 코드는 위 예시에 나온 것 처럼 xml 파일에 정의된 암호화된 문자열을 가져와서 복호화 해서 연결문자열을 만든다는 정도로만 이해 하시면 될듯 합니다.

이제 생성자로 개체를 생성 했으니 어떻게 사용할 까요..

예제를 보시죠..

 SqlDB db = new SqlDB("con");
 bool hasError = false;
 SqlParameter[] param1 = {
             new SqlParameter("@RETURNVALUE", SqlDbType.Int),
             new SqlParameter("@DATA_INTERFACE_TYPE_CODE", SqlDbType.Char, 1)
         };
 param[0].Direction = ParameterDirection.ReturnValue;

 try
 {        
     db.BeginTransaction();
 
     db.ExecuteNonQuery(false, false, CommandType.StoredProcedure
                        , "[dbo].[SP_NOTI_ADD_MEETING]", param1, flag);
     int returnValue = db.GetReturnValue(param1[0]);
 
     if(returnValue == 0)
     {
         foreach (JoinedUserItem joinedUserItem in joinedUsers)
         {
             SqlParameter[] param = {
                new SqlParameter("@DATA_INTERFACE_TYPE_CODE", SqlDbType.Char, 1),
                new SqlParameter("@ITEM_ID", SqlDbType.NVarChar, 27)
             };
             db.ExecuteScalar(false, false, CommandType.StoredProcedure
                           , "[dbo].[SP_EP_INTERFACE_ADD_RESERVATION_INFO]"
                           , param, "I", "M" + item.MeetingSeq);
         }
     }
 }
 catch (Exception ex)
 {
     hasError = true;
     db.RollBackTransaction();
     throw ex;
 }
 finally
 {
     if (!hasError)
     {
         db.CommitTransaction();
     }
     db.Dispose();
 }

위 예제는 너무 직관적(?) 이라 따로 설명이 필요 없을 듯 합니다만..조금 설명을 덧 붙여 보겠습니다.

BeginTransaction() 메서드는 프로그래밍적으로 트랜잭션을 이용할 때 이용합니다.
프로그래밍적으로 트랜잭션을 사용하면 프로시저 단에서는 이를 고려하여야 겠죠?

위 예제 처럼 처음 연결 후 트랜잭션을 열고 여러번의 쿼리를 한 후에 롤백 혹은 커밋을 할 수 있습니다.

이때 주의 점은 ExecuteNonQuery 와 같은 쿼리 메서드의 파라메터 설정입니다.(Execute~  메서드는 모두 대동소이합니다.)

BeginTransaction() 메서드를 통해 트랜잭션을 사용하는 경우 Execute~ 메서드의 파라메터 중 isTransaction 값은 반드시 false 여야 합니다. 이 값이 true 일 때면 해당 쿼리에서만 트랜잭션을 사용해야 할 경우입니다.

또 주의 해야 할 파라메터는 mustCloseConnection 의 값 또한 위 예제 처럼 false 가 되어야 합니다.

이 값이 true 라는 것은 이 쿼리가 종료되는 연결을 종료 한다는 의미가 되겠습니다.

위 예제 같은 경우 이 값이 true가 되어 버리면 첫 쿼리 이후에 연결을 끊어 버려 논리적인 오류가 발생되겠지요..(런타임 오류가 아닙니다.) 그리고 트랜잭션 수만 증가가 되겠지요 커밋이나 롤백을 하지 않았으니까요.

14행 처럼 GetReturnValue() 제너릭 메서드를 통해 리턴값을 받아 올 수도 있습니다.

7행 처럼 파라메터의 Direction 을 설정하고 14행 처럼 받아 오면 됩니다.

물론 프로시저에서 RETURN 을 해줘야 겠지요.

Async 메서드와 DataSet의 Update메서드도 있긴 하지만 사용빈도가 현저히 낮기 때문에 자질구레한 설명은 생략 합니다.


마지막 업데이트 : (1/5/2011 5:19:31 PM)




첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기

Security.AriaProvider Ver 1.2.1.2

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (8/26/2006 2:17:59 AM) Viewing : 7813
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



마지막 업데이트 : (8/29/2006 3:27:18 PM)

TAG : 없음



Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기

Security.AriaProvider Ver 1.2.2.2

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (8/29/2006 12:54:53 PM) Viewing : 3672
복호화 하는 메소드의 버그를 발견 하였다.

문제의 부분은 한글데이터의 경우에만 발생 하는데.
16바이트의 블럭으로 쪼개서 암호화를 한후
다시 16바이트씩 복호화를 해서 문자열로 연결시켰을 시에 문제가 발생 하였다.

한글의 경우 2바이트이기 때문에 만약 16번지 바이트와 17번지 바이트에 한글이 위치 한다면
복호화를 할때 16번지 바이트까지 짤라서 복호화를 하고
17번지는 다음 배열에 시작점으로 해서 복호화를 했었기 때문에
한글이 깨지는 문제가 발생 하였다.

그리하여
먼저 바이트의 배열을 생성하여 통합한후에 한꺼번에 문자열로 복호화 하는 방법으로 변경 하였으며
잘 작동된다..

변경된 코드는 아래와 같다.

[소스코드]

/// <summary>
/// 암호화된 문자열을 받아 복호화한다.
/// </summary>
/// <param name="inputText">암호화된 문자열입니다.</param>
/// <returns>복호화된 문자열입니다.</returns>
public string DecryptFromString(string inputString)
{
    byte[] dest = new byte[inputString.Length];
    if (String.IsNullOrEmpty(inputString))
    {
        return inputString;
    }
    else
    {
        this.Decrypt(inputString);

        for (int i = 0, j = 0; i < this.plainTextBlock.Length; i++, j += 16)
        {
            Buffer.BlockCopy(this.plainTextBlock[i], 0, dest, j, 16);
        }
        return Encoding.Default.GetString(dest);
    }
}

/// <summary>
/// 암호화된 byte[]을 받아 복호화한다.
/// </summary>
/// <param name="inputByteArray">암호화된 byte[]입니다.</param>
/// <returns>복호화된 문자열입니다.</returns>
public string DecryptFromByteArray(byte[] inputByteArray)
{
    byte[] dest = new byte[inputByteArray.Length];
    if (inputByteArray == null || inputByteArray.Length == 0)
    {
        return String.Empty;
    }
    else
    {
        this.Decrypt(inputByteArray);

        for (int i = 0, j = 0; i < this.plainTextBlock.Length; i++, j += 16)
        {
            Buffer.BlockCopy(this.plainTextBlock[i], 0, dest, j, 16);
        }
        return Encoding.Default.GetString(dest);
    }
}


구현환경
.NET Framework 2.0
Microsoft Visual Studio.NET 2005
Microsoft Windows XP SP2



마지막 업데이트 : (8/29/2006 3:26:06 PM)

TAG : 없음



첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (1)
syj2909님의 글 (7/14/2009 8:27:51 PM)
이런식으로 암호화 및 복호화 결과데이터를 멤버변수를 사용할 경우

서로다른 객체에서 암호화, 복호화를 나누어서 할경우 복호화가 가능하나여?

한 객체내에서 암호화 했는 대상데이터를 멤버에 집어넣구 복호화때 사용하게 되면.. 객체 새로생성할경우

메모리가 날라가는데.. 문제가 되진않아요?



댓글 쓰기

Core.SqlDB ver 2.1.3.0

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (8/21/2006 2:59:55 PM) Viewing : 3015
이 클래스는 사실..
너무나 Clear 하기 때문에 주석을 달고 말고 할것도 없다..ㅡ.ㅡ;

일단 생성자를 보면
기본 생성자는 private로 숨겨져 있다.
사용하지 말라는 얘기다..ㅋ~


[소스코드]

        #region Constructor
        private SqlDB(){}
        public SqlDB(string connectionString)
        {
            this.connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings[connectionString].ToString());
        }
        #endregion

이것은 web.config에서 정의 되어 있는 연결 문자열을 읽어 온다.

web.config에서는 아래와 같이 정의 되어 있다.


[소스코드]

  <connectionStrings>
    <add name="con" connectionString="server=(local);uid=sa;pwd=password;database=myhome;Asynchronous Processing=true;"/>
  </connectionStrings>

그리고 개체를 생성 하는 방법은
아래와 같다.


[소스코드]

            SqlDB db = new SqlDB("con");

이제 몇개의 메소드를 설명을 해 보겠다.

먼저 AssignParameters 메소드를 살펴 보면
이 메소드의 역활은 매개변수로 들어 온 SqlParameter[] 에 각각 값을 넣어 주는 역할을 한다.
아마도 엔터프라이즈 템플릿에서 그대로 따온 메소드인것 같다..이름과 전반적인 기능을 같다..
구현만 조금..다를 뿐.

[소스코드]

            for (int i = 0, j = 0; i < parameters.Length; )
            {
                if (parameters[i].Direction != ParameterDirection.ReturnValue && parameters[i].Direction != ParameterDirection.Output)
                {
                    if (values[j] == null)
                    {
                        parameters[i].Value = DBNull.Value;
                        i++;
                        j++;
                    }
                    else
                    {
                        parameters[i].Value = values[j];
                        i++;
                        j++;
                    }
                }
                else
                {
                    i++;
                }
            }

보면 알겠지만.
ParameterDirection이 ReturnValue 와 Output은 값이 할당되어 있지 않기 때문에
SqlParameter[]에도 값을 할당 하지 않는다.


다른 메소드는 특별히 설명하고 말고 할게 없다..
여기서 비즈니스레이어에서 호출되어지는 메소드는 몇개가 있는데,
Excute~로 시작되는 메소드가 대표적이다
대부분 이 메소드마 호출 되면 대부분의 작업을 처리 해준다.
이름도 너무나 Clear하여서.
ExcuteNonquery()
ExcuteScalar()
ExcuteReader()
ExcuteDataset()

이 4개의 메소드는 많이 재정의가 되어 있으면 때에 따라 선택에서 쓰면 된다.

그리고 앞에 Async라는 단어가 붙어 있는것은 이번 버전에서 새로 나온 MARS를 지원해주게끔 하기 위해 추가한 메소드들이다.
즉 비동기 쿼리를 위한 메소드이다.

사용법은 동일하지만 MARS에 대한 것은 MSDN을 참조 하기 바란다.

마지막에 보여줄 Transaction관련한 메소드가 3개가 있는데..
트랜잭션 처리를 위해 만든 메소드이다.
예를 들어 트랜잭션을 사용하는데..
한번 DB를 오픈하고 여러번의 쿼리 혹은 프로시저를 호출(프로그램상에서 메소드로 호출)하고
마지막에 커밋 혹은 롤백을 할 때 사용한다.

[소스코드]

        internal bool AddFile(List<BoardFileItem> fileList, Guid postId)
        {
            SqlDB db = new SqlDB(this.connectionString);
            db.BeginTransaction();
            foreach (BoardFileItem item in fileList)
            {
                SqlParameter[] param ={
                    new SqlParameter("@PostId", SqlDbType.UniqueIdentifier),
                    new SqlParameter("@RealName", SqlDbType.VarChar,128),
                    new SqlParameter("@VirtualName", SqlDbType.VarChar,32),
                    new SqlParameter("@FileSize", SqlDbType.Int),
                    new SqlParameter("@ContentType", SqlDbType.VarChar,64)
                };
                if (1 != db.ExecuteNonQuery(false, false, CommandType.StoredProcedure, "Board_AddFile", param, item.PostId, item.RealFileName, item.VirtualFileName, item.Size, item.ContentType))
                {
                    db.RollBackTransaction();
                    return false;
                }
            }
            SqlParameter[] param1 = {
                    new SqlParameter("@PostId", SqlDbType.UniqueIdentifier)
            };
            if (1 != db.ExecuteNonQuery(false, false, CommandType.StoredProcedure, "Board_FileCheck", param1, postId))
            {
                db.RollBackTransaction();
                return false;
            }
            db.CommitTransaction();
            return true;
        }

위 예제는 이를 사용 하는 법을 알려 준다.
위 예제는 여러개의 파일을 업로드 하고 그 정보를 디비에 인서트 하는 코드이다.

트랜잭션을 유지 하기 위해서는 커넥션은 한번만 열어야 한다..
당연한 얘기 겠지만...

각각의 Excute~메소드에 보면 두번째 파라메터로 mustCloseConnection이라는 flag가 있다.
이는 정의 하지 않으면 디폴트 값으로 true가 되어
한번 쿼리 후에 커넥션을 닫게 설계되었지만.
트랜잭션을 사용하기 위해서는 false로 넣어 연결을 계속 유지 해야 한다..

이 유지된 연결은 커밋 혹은 롤백 할때 닫혀진다.


구현환경
.NET Framework 2.0
Microsoft Visual Studio.NET 2005
Microsoft Windows XP SP2



마지막 업데이트 : (8/21/2006 2:59:55 PM)

TAG : 없음



첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기



<< < 1 2 > >>