Communicator 클래스의 코드 분석(CNG 예제)
Communicator.cs 파일은 CNG(Cryptography Next Generation) 보안 통신 예제의 암호화 및 암호 해독 메서드를 캡슐화합니다.이 파일은 Communicator라는 클래스 하나로만 구성되어 있습니다.이 클래스에는 다음 단원에서 설명하는 멤버와 메서드가 들어 있습니다.
클래스 멤버
클래스 생성자
Dispose 메서드
StoreDSKey 메서드
Send_or_Receive_PublicCryptoKey 메서드
SendMessage 메서드
ReceiveMessage 메서드
이 항목에 언급된 예제에 대한 개요 및 버전에 대한 설명은 CNG(Cryptography Next Generation) 보안 통신 예제를 참조하십시오.
클래스 멤버
Communicator 클래스에는 다음과 같은 전용 멤버가 들어 있습니다.
CngKey m_DSKey
이 멤버는 Communicator.StoreDSKey에서 디지털 서명 키를 저장하는 데 사용됩니다.
ECDiffieHellmanCng m_ECDH_Cng
이 멤버는 생성자에서 ECDiffieHellmanCng 클래스의 인스턴스를 저장하는 데 사용됩니다.ReceiveMessage 및 SendMessage 메서드는 이 멤버를 사용하여 키 자료를 파생합니다.
string m_ECDH_local_publicKey_XML
이 멤버는 생성자에서 로컬 공개 ECDH(Elliptic Curve Diffie-Hellman) 암호화 키의 XML 문자열 표현을 저장하는 데 사용됩니다.Alice, Bob 및 Mallory는 Send_or_Receive_PublicCryptoKey 메서드를 사용하여 이 XML 문자열을 교환합니다.
ECDiffieHellmanPublicKey m_ECDH_remote_publicKey
이 멤버는 Send_or_Receive_PublicCryptoKey 메서드에서 원격 공개 ECDH 암호화 키를 저장하는 데 사용됩니다.
Communicator 클래스는 다음과 같은 공용 멤버도 제공합니다.
ChannelManager ChMgr
이 멤버는 Alice, Bob 및 Mallory가 명명된 파이프 서비스를 제공하는 데 사용됩니다.
클래스 생성자
public Communicator(string mode, string ChannelName)
생성자는 다음과 같은 세 개의 개체를 만듭니다.
521비트의 키 크기와 난수 키 쌍을 사용한 ECDiffieHellmanCng 클래스의 인스턴스
m_ECDH_Cng = new ECDiffieHellmanCng(521)
결과 개체는 Communicator 클래스에 전용 멤버로 바인딩됩니다.각 Communicator 개체는 이 클래스의 단일 인스턴스를 만듭니다.
Alice 및 Bob은 각각 단일 Communicator 개체를 만들며 단일 m_ECDH_Cng 멤버에 액세스할 수 있습니다.Mallory는 두 개의 Communicator 개체를 만들어 하나는 Alice와 사용하고 다른 하나는 Bob과 사용합니다.따라서 Mallory는 두 m_ECDH_Cng 멤버에 액세스할 수 있습니다.
전용 XML 문자열로 나타낸 ECDH 공개 키
m_ECDH_XmlString = m_ECDH_CryptoKey.ToXmlString(ECKeyXmlFormat.Rfc4050)
ECDiffieHellmanCng.ToXmlString 메서드는 ECKeyXmlFormat.Rfc4050 형식을 사용하여 공개 ECDH 키를 serialize합니다.
예제의 버전 2-5에서는 Alice가 다음 코드 명령문을 사용하여 Run 메서드를 통해 Bob에게 결과 XML 문자열을 전송합니다.
Alice.Send_or_Receive_PublicCryptoKey("send", MyColor);
ChannelManager 클래스의 공용 인스턴스
ChMgr = new ChannelManager(mode, ChannelName)
생성자는 다음 두 가지 매개 변수를 받습니다.
mode: 명명된 파이프를 만들 방법을 지정하는 문자열입니다.이 매개 변수는 "server" 또는 "client"일 수 있습니다.
ChannelName: 새 명명된 파이프를 식별하는 이름을 제공하는 문자열입니다.
Dispose 메서드
public void Dispose()
Communicator 클래스는 IDisposable 인터페이스를 상속하고 중요한 리소스를 즉시 해제하는 Dispose 메서드를 제공합니다.여기에는 m_ECDH_Cng, m_ECDH_local_publicKey_XML 및 ChMgr 개체가 포함됩니다.
각 개체는 C# using 명령문 내에서 만들어지므로 범위를 벗어난 개체가 즉시 해제됩니다.
StoreDSKey 메서드
public void StoreDSKey(byte[] DSKeyBlob)
이 메서드는 바이트 배열에 들어 있는 BLOB(이진 대형 개체)를 받습니다.또한 CngKey.Import(array<Byte[], CngKeyBlobFormat) 메서드를 사용하여 키 BLOB에서 디지털 서명 키를 추출합니다.키는 다음과 같은 코드를 통해 저장됩니다.
m_DSKey = CngKey.Import(DSKeyBlob,CngKeyBlobFormat.Pkcs8PrivateBlob);
Alice, Bob 및 Mallory는 다음과 같은 버전에서 Run 메서드를 통해 StoreDSKey 메서드를 호출합니다.
버전 3-5에서 Alice, Bob 및 Mallory는 이 메서드를 사용하여 공개적으로 전송된 동일한 키를 저장합니다.
버전 4 및 5에서 Alice와 Bob은 이 메서드를 두 번째로 호출하고 m_DSKey 멤버를 개인적으로 전송된 키로 덮어씁니다.
Send_or_Receive_PublicCryptoKey 메서드
Send_or_Receive_PublicCryptoKey(string mode, int color)
이 메서드는 다음 두 가지 매개 변수를 받습니다.
mode: 키를 보내는 파이프 서버를 만들지 아니면 키를 받는 파이프 클라이언트를 만들지를 지정하는 문자열입니다.이 매개 변수는 "server" 또는 "client"일 수 있습니다.
color: 키를 표시하는 데 사용되는 색을 지정하는 정수입니다.
Send_or_Receive_PublicCryptoKey 메서드는 CommunicatorReceiveMessage 및 SendMessage 메서드와 비슷하지만 암호화된 메시지 대신 암호화되지 않은 암호화 키를 주고받는다는 점이 다릅니다.ReceiveMessage 및 SendMessage 메서드는 키를 암호화 및 해독하므로 암호화 키에 사용할 수 없습니다.
키가 교환되면 예제의 버전 3-5에서는 키의 디지털 서명의 유효성을 검사합니다.버전 3에서는 PublicChannel 명명된 파이프를 통해 전송된 디지털 서명을 사용합니다.Mallory는 이 서명을 가로채서 Alice와 Bob에게 전송하는 대체된 키와 메시지에 서명하는 데 사용합니다.버전 3에서 Alice, Bob 및 Mallory는 동일한 디지털 서명 키를 사용하므로 서명 유효성 검사가 항상 성공합니다.
참고
버전 4 및 5에서는 개인 디지털 서명을 사용하여 키와 메시지에 서명하고 보안 경고를 표시합니다.이 버전은 Alice와 Bob에게만 주어지므로Mallory는 해킹이 발각되었음을 알지 못합니다.
SendMessage 메서드
public bool SendMessage(string plainTextMessage, bool fShowMsg)
Alice, Bob 및 Mallory는 Run 메서드에서 이 메서드를 호출합니다.이 메서드는 다음과 같은 단계에 따라 메시지를 암호화하고 디지털 서명하고 전송합니다.
fShowMsg 값이 true이면 일반 텍스트 메시지를 표시합니다.
다음 코드를 사용하여 메시지를 유니코드 바이트 배열로 변환합니다.
byte[] UnicodeText = Encoding.Unicode.GetBytes(plainTextMessage);
메시지를 일반 텍스트로 전송할지 여부를 결정합니다.예제가 버전 1로 실행되는 경우 SendMessage는 다음 코드를 사용하여 메시지를 전송한 후 반환됩니다.
ChMgr.SendMessage(UnicodeText);
ECDiffieHellmanCng.DeriveKeyMaterial(ECDiffieHellmanPublicKey) 메서드를 호출하여 키 자료를 파생합니다.
byte[] aesKey = m_ECDH_Cng.DeriveKeyMaterial(m_ECDH_remote_publicKey)
임시 Aes 개체를 만듭니다.
Aes aes = new AesCryptoServiceProvider()
4단계에서 파생한 키 자료를 사용하여 Aes 개체를 초기화합니다.
aes.Key = aesKey;
암호화된 문자열을 보유할 임시 MemoryStream 개체를 만듭니다.
임시 CryptoStream 개체를 만들고 이 개체를 사용하여 메시지를 암호화한 다음 MemoryStream 개체에 씁니다.
암호화 텍스트 및 초기화 벡터를 저장합니다.
iv = aes.IV ciphertext = ms.ToArray();
예제가 버전 3, 4 또는 5로 실행되는 경우 다음과 같이 암호화 텍스트에 서명합니다.
임시 ECDsaCng.ECDsaCng(CngKey) 개체를 만듭니다.
ECDsaCng ecdsa = new ECDsaCng(m_DSKey)
개체의 HashAlgorithm 속성을 Sha512 보안 해시 알고리즘으로 초기화합니다.
ecdsa.HashAlgorithm = CngAlgorithm.Sha512
암호화 텍스트에 서명하여 디지털 서명을 만듭니다.
signature = ecdsa.SignData(ciphertext);
다음과 같이 출력 메시지를 준비합니다.
메시지의 초기화 벡터, 암호화 텍스트 및 서명의 길이를 보유할 3바이트 배열을 만듭니다.
이전 단계의 길이 배열, 초기화 벡터, 암호화 텍스트 및 서명을 보유할 네 개의 System.Collections.Generic.List<T> 개체를 만듭니다.
네 개의 System.Collections.Generic.List<T> 개체를 연결하고 단일 출력 메시지 바이트 배열로 변환합니다.
byte[] message = list1.ToArray();
출력 메시지를 전송합니다.
ChMgr.SendMessage(message)
ReceiveMessage 메서드
public string ReceiveMessage()
Alice, Bob 및 Mallory는 Run 메서드에서 이 메서드를 호출합니다.이 메서드는 메시지를 받아 암호를 해독하고 디지털 서명의 유효성을 검사합니다.
이 메서드에는 메시지가 매개 변수로 전달되지 않습니다.대신 Communicator 클래스의 ChannelManager 멤버에서 다음 코드를 사용하여 메시지를 읽습니다.
byteBuffer = ChMgr.ReadMessage();
ReceiveMessage 메서드는 다음 단계를 수행합니다.
메시지가 일반 텍스트로 전송되었는지 여부를 확인합니다.예제의 버전 1이 실행되는 경우에는 메시지가 일반 텍스트이므로 암호를 해독할 필요가 없습니다.이러한 경우 다음 코드를 사용하여 메시지를 ASCII 문자열로 변환한 후 반환합니다.
AsciiMessage = Encoding.Unicode.GetString(byteBuffer);
메시지를 여러 구성 요소로 나눕니다.버전 2-5에서는 메시지가 암호화됩니다.이러한 경우 메시지가 별도의 바이트 배열 세 개로 분할됩니다.첫 번째 배열에는 초기화 벡터가 들어 있고, 두 번째 배열에는 암호화 텍스트가 들어 있고, 세 번째 배열에는 암호화 텍스트의 디지털 서명이 들어 있습니다.
fVerbose 플래그가 설정되어 있으면 초기화 벡터, 암호화 텍스트 및 서명을 ASCII 텍스트로 표시합니다.
키 자료를 파생합니다.Communicator 클래스의 전용 ECDiffieHellmanCng 멤버인 m_ECDH_Cng는 다음 코드와 같이 ECDiffieHellmanCng.DeriveKeyMaterial 메서드를 사용하여 공유된 키 자료를 파생합니다.
byte[] aesKey = m_ECDH_Cng.DeriveKeyMaterial(m_ECDH_remote_publicKey);
AesCryptoServiceProvider 개체를 인스턴스화하여 Aes 개체를 만듭니다.
Aes aes = new AesCryptoServiceProvider()
이전 단계에서 파생된 키 자료와 초기화 벡터를 사용하여 Aes 개체를 초기화합니다.
System.IO.MemoryStream 및 System.Security.Cryptography.CryptoStream 개체를 사용하여 메시지의 암호를 해독합니다.
암호가 해독된 메시지를 표시합니다.
버전 3-5에서는 디지털 서명을 사용하여 메시지 암호화 텍스트의 유효성을 검사합니다.버전 3에서는 Alice, Bob 및 Mallory가 동일한 서명을 사용하므로 보안 경고를 표시하지 않습니다.버전 4에서는 메시지 암호화 텍스트의 서명이 잘못된 경우 보안 경고를 표시합니다.그러나 Alice와 Bob에게만 버전 4가 제공되므로 Mallory는 경고를 볼 수 없습니다.버전 5에서는 암호화 키의 서명이 잘못된 경우 메시지를 전송하고 유효성을 검사하기 전에 프로그램이 종료됩니다.