2014-11-13 2 views
1

RSA로 데이터를 암호화하는 Windows 8.1 (C#)에서 메트로 응용 프로그램을 개발하려고합니다.
마지막 목표는 주어진 공개 키를 사용하여 이미지 (큰 바이트 배열)를 암호화하고 멀리 보내어 다른 플랫폼에서 해독되도록하는 것입니다 (개인 키를 유지하고 사용함).큰 데이터 버퍼를 암호화하는 WinRT RSA

테스트 목적으로 키 작성, 데이터 암호화 및 암호 해독과 같은 모든 작업을 메트로 응용 프로그램에서 수행하려고합니다.

위의 코드는 작은 문자열에 적합합니다.

//Key creation 
AsymmetricKeyAlgorithmProvider provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); 
CryptographicKey key = provider.CreateKeyPair(1024); 
IBuffer privateKey = key.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey); 
IBuffer publicKey = key.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey); 
String publicKeyStr = CryptographicBuffer.EncodeToBase64String(publicKey); 
String privateKeyStr = CryptographicBuffer.EncodeToBase64String(privateKey); 

//Encrypt 
IBuffer encryptionKeyBuffer = CryptographicBuffer.DecodeFromBase64String(publicKeyStr); 
AsymmetricKeyAlgorithmProvider encodingProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); 
CryptographicKey encryptKey = encodingProvider.ImportPublicKey(encryptionKeyBuffer, CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey); 
IBuffer buf = CryptographicBuffer.ConvertStringToBinary("Hello World!", BinaryStringEncoding.Utf16BE); 
var encrypted = CryptographicEngine.Encrypt(encryptKey, buf, null); 

//DecrYpt 
IBuffer decryptKeyBuffer = CryptographicBuffer.DecodeFromBase64String(privateKeyStr); 
AsymmetricKeyAlgorithmProvider decryptionProvider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); 
CryptographicKey decryptKey = decryptionProvider.ImportKeyPair(decryptKeyBuffer, CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey); 
IBuffer decryptedBuf = CryptographicEngine.Decrypt(decryptKey, encrypted, null); 
Debug.WriteLine(CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf16BE, decryptedBuf)); // Display "Hello World!", great 

문제는 내가 큰 데이터를 암호화 할 때, 내가 암호화 방법에 예외를 얻을 것이다 "값이 예상 범위를 벗어하지 않습니다."

예를 들어 코드 :

int size = 59; 
StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < size; i++) 
{ 
    sb.Append("a"); 
} 
IBuffer buf = CryptographicBuffer.ConvertStringToBinary(sb.ToString(), BinaryStringEncoding.Utf16BE); 
var encrypted = CryptographicEngine.Encrypt(encryptKey, buf, null); 

는 ... = 크기 (58)를 작동하지만 크기 = 59 제한 크기 암호화에 enxception을 발생 키 크기에 따라 달라집니다. 이것은 1024 키 크기에 대한 제한이지만 512는 약간 작고 반대입니다.

최종 버퍼는 이미지이므로 내 제한보다 훨씬 큽니다 ... 그리고 버퍼가 제한된 이유를 알지 못합니다.

내가 잘못 했습니까? 내 코드에 문제가 있습니까? 이 방법으로 큰 데이터를 암호화하는 방법에 대한 아이디어가 있습니까?

답변

3

암호화 된 평문의 크기는 키 크기에 따라 다릅니다. m 메시지를 암호화 할 때 모듈화 지수의 기본 값은 me (mod n)입니다. n보다 크거나 같은 메시지는 모듈 n으로 인해 다른 메시지로 바뀝니다.
m ≡ m (MOD N) w>N 다음과 m E (MOD N) E (MOD N) 승 = 경우. 암호문을 해독하면 원본 메시지가 다시 표시되지 않습니다. 이 때문에 라이브러리는 오류를 발생시킵니다.

해결책은 hybrid encryption을 사용하는 것입니다. 먼저 생성 된 임의 키를 사용하여 AES와 같은 symmetric cipher으로 데이터를 암호화합니다. 이제 AES의 무작위 키는 최대 256 비트이므로 RSA에 1024 비트 키가 있습니다 (패딩 때문에 512 비트 키에 맞지 않습니다). 공개 키로 AES 키를 암호화하고 암호화 된 데이터와 함께 암호화 된 키를 보냅니다.
다른 한편으로는 개인 키를 사용하여 임의의 AES 키를 복구하고이를 사용하여 데이터의 암호를 해독합니다.

SymmetricKeyAlgorithmProvider sp = SymmetricKeyAlgorithmProvider 
     .OpenAlgorithm(SymmetricAlgorithmNames.AesGcm); 

다른 권장 모드는 SymmetricAlgorithmNames.AesCcm입니다. GCM 및 CCM은 CBC가 제공하지 않는 인증 (무결성)을 제공합니다.

+0

빠른 답변 감사드립니다. 따라서 RSA를 사용하여 AES 키만 암호화하고 "실제"데이터는 AES로 암호화 된 상태로 유지하는 것이 원칙입니다. 나는 정확하게 이해 했는가? – Bjorn

+0

예, 정확히 맞음 –

+2

Nitpick : 적절한 패딩을 사용하면 512 비트 RSA 키에 256 비트 AES 키 (SHA1이있는 OAEP에는 41 바이트의 오버 헤드가 있음)가 없습니다. 하지만 512 비트 RSA 키가 완전히 깨 졌으므로이 점은 중요하지 않습니다. – CodesInChaos

관련 문제