2015-06-29 7 views
1

Я пытаюсь зашифровать очень длинный текст, используя общедоступные и закрытые ключи сертификата X509. В частности, я пытаюсь воспроизвести этот код MSDN: https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.publickey(v=vs.90).aspxMemoryStream: Encoding

Однако вместо шифрования файла я хочу зашифровать строку. Поэтому я пытаюсь адаптировать код для использования MemoryStreams.

Проблема в том, что каждый раз, когда я пытаюсь прочитать содержимое потока, у него есть странные символы. Поэтому, когда я пытаюсь вызвать webservice (asmx) и отправив ему шифрованный текст, он выходит из строя.

Это мой код. Я попытался использовать UTF32, UTF8, UTF7 и ASCII.

Private Shared Function encryptText(ByVal token As String, ByVal rsaPublicKey As Security.Cryptography.RSACryptoServiceProvider) As String 
    Dim aesManaged As New Security.Cryptography.AesManaged() 
    Dim transform As Security.Cryptography.ICryptoTransform = Nothing 
    Dim outStreamEncrypted As Security.Cryptography.CryptoStream = Nothing 
    Dim outFsaux As New IO.MemoryStream() 
    Dim outFs As New IO.StreamWriter(outFsaux, Text.Encoding.ASCII) 
    Dim inFs As New IO.MemoryStream(Text.Encoding.ASCII.GetBytes(token)) 
    Dim cipherText As String = String.Empty 


    Try 
     aesManaged.KeySize = 256 
     aesManaged.BlockSize = 128 
     aesManaged.Mode = Security.Cryptography.CipherMode.CBC 

     Dim keyFormatter As New Security.Cryptography.RSAPKCS1KeyExchangeFormatter(rsaPublicKey) 
     Dim keyEncrypted As Byte() = keyFormatter.CreateKeyExchange(aesManaged.Key, aesManaged.GetType()) 

     Dim LenK(3) As Byte 
     Dim LenIV(3) As Byte 

     Dim lKey As Integer = keyEncrypted.Length 
     LenK = BitConverter.GetBytes(lKey) 
     Dim lIV As Integer = aesManaged.IV.Length 
     LenIV = BitConverter.GetBytes(lIV) 

     outFs.Write(LenK) 
     outFs.Write(LenIV) 
     outFs.Write(keyEncrypted) 
     outFs.Write(aesManaged.IV) 

     transform = aesManaged.CreateEncryptor() 

     outStreamEncrypted = New Security.Cryptography.CryptoStream(outFs.BaseStream, transform, Security.Cryptography.CryptoStreamMode.Write) 
     Dim count As Integer = 0 
     Dim offset As Integer = 0 

     Dim blockSizeBytes As Integer = aesManaged.BlockSize/8 
     Dim data(blockSizeBytes) As Byte 
     Dim bytesRead As Integer = 0 

     Do 
      count = inFs.Read(data, 0, blockSizeBytes) 
      offset += count 
      outStreamEncrypted.Write(data, 0, count) 
      bytesRead += blockSizeBytes 
     Loop While count > 0 

     inFs.Flush() 
     outStreamEncrypted.FlushFinalBlock() 

     outFsaux.Position = 0 
     cipherText = System.Convert.ToBase64String(outFsaux.ToArray()) 
    Finally 
     If inFs IsNot Nothing Then inFs.Dispose() 
     If outFs IsNot Nothing Then outFs.Dispose() 
     If outStreamEncrypted IsNot Nothing Then outStreamEncrypted.Dispose() 
     If transform IsNot Nothing Then transform.Dispose() 
    End Try 

    Return cipherText 
End Function 

ОБНОВЛЕНИЕ:

Спасибо за помощь. Я также обновил вышеуказанный код.

Теперь я могу правильно шифровать текст. Тем не менее, мне все еще нужна помощь, чтобы адаптировать метод дешифрования. Он сбой при попытке создать переменную KeyDecrypted

Я знаю, что проблема заключается в том, что при шифровании он загружает некоторую информацию в начале строки шифрования, способ дешифрования которой невозможно восстановить должным образом после преобразования Base64.

Private Shared Function decryptText(ByVal token As String, ByVal rsaPrivateKey As Security.Cryptography.RSACryptoServiceProvider) As String 
    Dim aesManaged As New Security.Cryptography.AesManaged() 
    Dim inFs As IO.MemoryStream = New IO.MemoryStream(Convert.FromBase64String(token)) 
    Dim outFs As New IO.MemoryStream 
    Dim outStreamDecrypted As Security.Cryptography.CryptoStream = Nothing 

    Dim decipherText As String = String.Empty 

    aesManaged.KeySize = 256 
    aesManaged.BlockSize = 128 
    aesManaged.Mode = Security.Cryptography.CipherMode.CBC 

    Dim LenK() As Byte = New Byte(4 - 1) {} 
    Dim LenIV() As Byte = New Byte(4 - 1) {} 


    inFs.Seek(0, IO.SeekOrigin.Begin) 
    inFs.Seek(0, IO.SeekOrigin.Begin) 
    inFs.Read(LenK, 0, 3) 
    inFs.Seek(4, IO.SeekOrigin.Begin) 
    inFs.Read(LenIV, 0, 3) 

    Dim lengthK As Integer = BitConverter.ToInt32(LenK, 0) 
    Dim lengthIV As Integer = BitConverter.ToInt32(LenIV, 0) 

    Dim startC As Integer = lengthK + lengthIV + 8 
    Dim lenC As Integer = (CType(inFs.Length, Integer) - startC) 

    Dim KeyEncrypted() As Byte = New Byte(lengthK - 1) {} 
    Dim IV() As Byte = New Byte(lengthIV - 1) {} 

    inFs.Seek(8, IO.SeekOrigin.Begin) 
    inFs.Read(KeyEncrypted, 0, lengthK) 
    inFs.Seek(8 + lengthK, IO.SeekOrigin.Begin) 
    inFs.Read(IV, 0, lengthIV) 

    Dim KeyDecrypted As Byte() = rsaPrivateKey.Decrypt(KeyEncrypted, False) 
    Dim transform As Security.Cryptography.ICryptoTransform = aesManaged.CreateDecryptor(KeyDecrypted, IV) 


    Dim count As Integer = 0 
    Dim offset As Integer = 0 

    Dim blockSizeBytes As Integer = aesManaged.BlockSize/8 
    Dim data(blockSizeBytes) As Byte 

    inFs.Seek(startC, IO.SeekOrigin.Begin) 

    outStreamDecrypted = New Security.Cryptography.CryptoStream(outFs, transform, Security.Cryptography.CryptoStreamMode.Write) 
    Do 
     count = inFs.Read(data, 0, blockSizeBytes) 
     offset += count 
     outStreamDecrypted.Write(data, 0, count) 
    Loop While count > 0 

    outFs.Position = 0 
    Using rd As New IO.StreamReader(outFs) 
     decipherText = rd.ReadToEnd() 
    End Using 

    Return decipherText 
End Function 
+3

Результатом зашифрованного текста являются произвольные байты. Они могут * не * быть преобразованы в текст, ваш вызов StreamReader.ReadToEnd() будет случайным образом разбивать или уничтожать зашифрованные байтовые значения. Кодирование с Convert.ToBase64String() - общий подход. –

+0

@ HansPassant Спасибо за помощь. Я был бы рад Если бы вы могли проверить обновление – Rumpelstinsk

ответ

3

Шифрованный текст будет содержать непечатаемые символы, так как он будет использовать весь диапазон от 0 до 255 для каждого байта. Если вы хотите отправить текст шифрования в виде строки, я бы сначала закодировал шифровальный текст base64.

изменение

rd = New IO.StreamReader(outFsaux, Text.Encoding.ASCII) 
cipherText = rd.ReadToEnd() 

в

cipherText = System.Convert.ToBase64String(outFsaux.ToArray()) 

Синтаксис код может быть немного не так, я не программирую в VB.

+0

Спасибо за помощь. Я был бы рад Если бы вы могли проверить обновление – Rumpelstinsk

+1

, то кодировка base64 и декодирование без потерь. Все в потоке, когда вы его кодируете base64, будет в вашей декодированной версии base64. Вы обернули потоковик потока вокруг вашего потока, который не обязательно записывается в базовый поток, когда вы пишете в streamwriter. Вы не должны смешивать запись с потоком из разных вещей, которые обтекают поток. Вы можете попытаться направить флеш на свой стример прямо после написания вашего ключа и iv потоковому потоку, чтобы сразу же записать его в базовый поток. – DanL

+0

DanL, еще раз спасибо. Я, наконец, получил его работу, благодаря вашим комментариям. Я обнаружил еще 2 проблемы. Прежде всего, я нашел первую проблему с кодировкой функции шифрования, которую я мог решить самостоятельно. Я мог бы решить вторую проблему после промывки потоков. Я принял ваш ответ как решение: D – Rumpelstinsk