2011-11-09 3 views
1

데이터베이스에 저장되고 고객 중 한 명에게 전송되는 데이터를 암호화하는 작업이 주어졌습니다. 나는 최선의 방법은 비대칭 암호화를 사용하여 고객의 공개 키 아무도 암호화하지 않고 고객 (개인 키의 소유자)이 암호 해독 할 수 있도록하는 것이라고 생각했습니다.C# - 제 3 자 공개 키를 사용하여 제 3 자에게 보낸 데이터 암호화

고객의 공개 키, 알고리즘 유형 (RSA 또는 DSA) 및 만료일을 인증서를 관리하는 대신 데이터베이스에 저장하고 싶습니다. 문제는 공개 키를 저장하고 사용할 수있는 방법입니다. 테스트 할 다음과 같은 작은 프로그램을 만들었고 문제가 발생했습니다.

class Program 
{ 

    static void Main(string[] args) 
    { 
     const string publicKeyString = "30 81 89 02 81 81 00 c2 6e 7e e8 78 66 3d 74 fd a7 57 21 24 2d c0 ee 53 59 54 14 db f5 cb 5e 8c 64 c8 73 d5 83 d7 12 57 3f e2 92 54 9a 87 94 18 71 04 c8 b5 92 44 27 78 e9 d3 de cb 5f f6 93 75 c0 46 6b 50 c7 45 a8 38 f9 a1 83 8e 26 51 5a 8c 22 95 8e 2b 4c 10 ea c6 85 ed 02 ed 66 81 ef a3 55 15 ad 64 33 d3 bd ca 75 db 35 44 49 54 ef 6a ca 2a d5 90 a7 9b be 03 40 62 16 fd be 39 fb b6 f0 6b f8 f1 00 c0 c5 02 03 01 00 01"; 
     const string stringToEncrypt = "11111111111111111111"; 

     var encoding = new UTF8Encoding(); 
     var encryptedData = Encrypt(encoding.GetBytes(stringToEncrypt), encoding.GetBytes(publicKeyString)); 

     Console.WriteLine("**** Encrypted String ****"); 
     Console.WriteLine(encoding.GetString(encryptedData)); 

     var decryptedData = Decrypt(encryptedData); 

     Console.WriteLine("**** Decrypted String ****"); 
     Console.WriteLine(encoding.GetString(decryptedData)); 

     Console.ReadKey(); 


    } 

    static byte[] Encrypt(byte[] dataToEncrypt, byte[] publicKey) 
    { 

     var exponent = new byte[] { 1, 0, 1 }; 
     var rsa = new RSACryptoServiceProvider(); 
     rsa.ImportParameters(new RSAParameters() { Modulus = publicKey, Exponent = exponent }); 
     var encryptedData = rsa.Encrypt(dataToEncrypt, false); 
     return encryptedData; 
    } 

    static byte[] Decrypt(byte[] dataToDecrypt) 
    { 
     var cert = new X509Certificate2(@"C:\certs\BP_DEV_CERT_1024.p12", "password"); 
     var rsa = (RSACryptoServiceProvider) cert.PrivateKey; 
     var decryptedData = rsa.Decrypt(dataToDecrypt, false); 
     return decryptedData; 

    } 

} 

내가 얻을이 프로그램을 실행하면 "암호를 해독 할 수있는 데이터는 128 바이트의 계수의 최대 값을 초과합니다." 이것은 제가 사용하는 공개 키가 완전히 잘못되었음을 준비하는 방법을 믿게합니다. .

그래서 나는 몇 가지 알아야 할 것 같아요 :

  1. 을 나는 인증서의 공개 키를 복사 할 수 있습니다하지만이 데이터베이스에 어떻게 보관해야합니까?

  2. 공개 키 문자열을 적절한 바이트 배열로 제대로 변환해야합니까?

  3. 누군가가 가지고있는 다른 포인터.

+0

필자가 먼저해야 할 일은 바이트 배열 인 공개 키 (16 진 덤프)를 변환한다는 것입니다. – idflyfish

+1

문제가 해결되면 답변으로 게시해야합니다. –

+0

자신의 질문에 답하기 전에 잠시 기다려야 할 수도 있습니다.하지만 제발하십시오! – Marijn

답변

1

RSA와 다른 비대칭 알고리즘은 대량으로 데이터를 암호화하는 데 적합하지 않습니다. 최대 메시지 길이는 키 모듈러스보다 몇 바이트 작습니다. 물론 블록으로 데이터를 구성하고 RSA 암호화를 반복적으로 적용 할 수는 있지만 여전히 끔찍하게 느립니다. 대신 RSA는 대칭 암호에 대한 암호화 키를 교환하는 데 사용됩니다.

S/MIME을 사용하여 고객의 데이터를 암호화하는 것이 좋습니다. 보안을 위해 널리 검토 된 표준이며, 이미 프로토콜을 지원하는 라이브러리가있을 것입니다. 대부분의 전자 메일 클라이언트는 S/MIME을 지원하므로 고객은 이미 필요한 소프트웨어를 이미 가지고있을 것입니다.

S/MIME (및 PGP)은 AES — "콘텐츠 암호화 키"와 같은 대칭 암호 용 키를 생성하여 작동합니다. 이것은 메시지를 암호화하는 데 사용됩니다. 그런 다음 해당 대칭 키는 공용 RSA 키 —과 함께 각 수신자의 "키 암호화 키"—으로 암호화됩니다. 암호화 된 콘텐츠 암호화 키는 암호 텍스트와 함께 각받는 사람에게 전송됩니다.

+0

그러나 나는 데이터가 단지 짧은 문자열 일 뿐이라는 생각에 ... 20 바이트가 넘지 않아. – idflyfish

+0

@idflyfish 다른 문제는 암호문 (0-255 범위의 임의의 바이트)을 UTF-8이있는 문자열로 변환한다는 것입니다. UTF-8에서 문자에 매핑되지 않는 바이트 시퀀스가 ​​있기 때문에 암호문이 손상됩니다. 대신, 바이트 배열에서 텍스트를 생성하려면 Base-64 또는 hex와 같은 것을 사용하십시오. – erickson

+0

감사합니다. 문자열을 나타 내기 위해 16 진수를 사용했다. 훌륭하게 작동합니다. – idflyfish

관련 문제