当前位置: 首页 > 知识库问答 >
问题:

.NET用AES和128位初始化向量加密XML流

吕子真
2023-03-14

我在一个项目中工作,在这个项目中,我通过XML流向web服务发帖。在这种情况下,提供程序请求使用密码块链接(CBC)模式下的高级加密标准(AES)和128位初始化向量对路由xml进行加密。我是用VB.NET编码的,从我可以看出我已经满足了他们所有的加密要求,但当我提交帖子时,我总是得到一个“无效的路由输入加密”的错误响应。我没有做很多与加密,所以我希望有人与一些加密经验可以帮助我在这里。它失败是因为我没有正确地给IV加前缀吗?在AES中是否有一种将IV合并到密码数据的标准方法?还是加密本身有问题?我在这里呆了一段时间,尝试了几种不同的加密方法,但都没有成功。下面列出的是我的代码和加密要求的摘要。

>

  • 使用高级加密标准(AES)在密码块链(CBC)模式下使用128位初始化向量[AES]算法生成对称密钥。不要使用零字节初始化向量。

    使用AES对称密钥加密有效的路由输入xml文档。在得到的密码文本前缀128位初始化向量。(建议不要使用全部为0字节的初始化向量。)

    Base64对初始化向量和加密的路由输入xml文档进行编码。

    使用base64编码的初始化向量和加密的路由输入xml文档构建ENCRYPTED_RI xml元素。

    为明文路由输入xml文档生成SHA1哈希。

    使用公钥和RSA版本1.5算法[RFC 2437]加密连接的结果。

    Base64对加密的级联结果进行编码。

    使用base64编码的加密连接结果构建ENCRYPTED_KEY xml元素。

    Sub CreateEncryptionXML()
        '############
        '## CREATE AES KEY AND IV
        '############
        Dim SymKey() As Byte
        Dim IV() As Byte
        Dim aes As New AesCryptoServiceProvider
    
        Using myAes As Aes = System.Security.Cryptography.Aes.Create()
            myAes.KeySize = 128
            myAes.BlockSize = 128
            myAes.Mode = CipherMode.CBC
            myAes.Key = Encoding.UTF8.GetBytes("MyEncryptionKey1")
            myAes.IV = Encoding.UTF8.GetBytes("MyInitialVector1")
    
            SymKey = myAes.Key
            IV = myAes.IV
        End Using
    
        '############
        '## ENCRYPT ROUTING INPUT XML DOC
        '############
        Dim riXml As New XmlDocument
        riXml.Load("C:\routingdoc.xml")        
        aes.Key = SymKey
        aes.IV = IV
        aes.Mode = CipherMode.CBC
    
        ' Convert the plaintext string to a byte array.
        Dim plaintextBytes() As Byte = System.Text.Encoding.UTF8.GetBytes(riXml.OuterXml.ToString())
    
        ' Create the stream.
        Dim ms As New System.IO.MemoryStream
    
        ' Create the encoder to write to the stream.
        Dim encStream As New CryptoStream(ms, aes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write)
    
        ' Use the crypto stream to write the byte array to the stream.
        encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
        encStream.FlushFinalBlock()
    
    
        '############
        '## PREFIX CIPHER TEXT WITH IV
        '############
        Dim encRiXml() As Byte = ms.ToArray
        Dim arraySize As Integer = IV.Length + encRiXml.Length
        Dim Merged(arraySize) As Byte
        IV.CopyTo(Merged, 0)
        encRiXml.CopyTo(Merged, IV.Length)
    
        Dim Base64IVEncRiXML As String = Convert.ToBase64String(Merged)
    
        '******** I BELIVE EVERYTHING PAST HERE IS CORRECT BUT INCLUDED IT TO SHOW WHOLE PROCESS **********
    
        '############
        '## CREATE SHA1 HASH FOR PLAINTEXT ROUTING INPUT
        '############
        Dim hash() As Byte = New SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(riXml.OuterXml.ToString()))
    
        '############
        '## CONCATENATE THE SHA1 HASH OF PLAINTEXT ROUTING INPUT XML WITH AES KEY
        '############
        Dim arraySize2 As Integer = hash.Length + SymKey.Length
        Dim Merged2(arraySize2) As Byte
        hash.CopyTo(Merged2, 0)
        SymKey.CopyTo(Merged2, hash.Length)
    
        '############
        '## ENCRYPT CONCATENATED RESULT USING RSA
        '############
        Dim EncryptionKey As String = File.ReadAllText("C:\cert-1.txt").Replace("-----BEGIN CERTIFICATE-----" & vbCr & vbLf, "").Replace("-----END CERTIFICATE-----", "")
    
        TextBox1.Text = EncryptionKey
    
        Dim binaryCertData() As Byte = Convert.FromBase64String(EncryptionKey)
        Dim cert As X509Certificate2 = New X509Certificate2(binaryCertData)
        Dim xmlKey As String = cert.PublicKey.Key.ToXmlString(False)
        Dim objRSA As RSACryptoServiceProvider = New RSACryptoServiceProvider()
        objRSA.FromXmlString(xmlKey)
    
        Dim encrypted() As Byte = objRSA.Encrypt(Merged2, False)
    
        Dim RSAEncryptedSHA1HashAESKey As String = Convert.ToBase64String(encrypted)
    
        postStaticTest(RSAEncryptedSHA1HashAESKey, Base64IVEncRiXML)
    End Sub
    
    'PROVIDED SAMPLE OF XML OUTPUT FROM DOCUMENTATION
    '<?xml version="1.0" encoding="UTF-8"?>
    '<SECURE_REQUEST_GROUP>
    '<ENCRYPTED_KEY Algorithm=”http://www.w3.org/2001/04/xmlenc#rsa-1_5” >
    'bXcCaS97p8TtGzlgZ9ogRcEAaw1D1OQCpk1AQFfWYE5J2CheNtRBpuME+uB3wSkwjIWftkYxQ5JRTQ3Qhz7LrCM+TOORl2lFFTpVC9zGUP1xndfT6EQONViV0XGJieWCzXNyjO3XpEl7IdntkVKucrDN9gA7wlimUdw4Ya5sn08=
    '</ ENCRYPTED_KEY>
    '< ENCRYPTED_RI Algorithm=”http://www.w3.org/2001/04/html" target="_blank">xmlenc#aes128-cbc”>
    '9BWPkFDt0Ua/2gN9+BDT9XbYHBuadEREIV1EUmvon/jSr0HkndD/9lBo95H3UYD12TL3wmXVSqi7Ak/QqxzmVRDMgw2Wy0Ezdc3eaA9tOE1c49ZcaZpGM23R1BOazTGdky5v2+oBvSj4a+Ry/aJynvzKvxpTYd15IKOOzPsF/n89Oj6XdjA1TTdn2FCEwo6IkPi0D5QK2i1i/pilEyrrSYQ0oWkYc6ON/OQyL/oHlkBXk0zzQd1HBPOde4/3C6ceajUTvqiIlP6dRBHe6DZ3Ps34g7326jg3koh59RYao/0StgpF3wTJaZ/W36nqlpT3aeoLa/5oKh4A7DjHbYCHTw1uYkPXVGLFl6zTpFRw8hGkPfBRZmS5lXnQl6xidqftb+fx61yBj80/FHAlvmUzBsSQZggeXzBjqlVoWudCuGdC5QH1xKBWrm8haS2UIEdK/DH8fC13oFMpS++C7HTc/u9N8iH6qF0GimxYHvhKwdk3iw/hxrw5Bv1/tQjI1snJm9U1HnokDwG5BWZJp8jBuPgJIapc/DQgIEbM+3NMJXoB/ed9PquPFPPlfoo4E13a3PZPYIDImnLkOjvdPMrZ8A==
    '</ ENCRYPTED_RI>
    '</SECURE_REQUEST_GROUP>
    
  • 共有1个答案

    毛正浩
    2023-03-14

    仍然有几个未解决的实现问题(我想我已经通过使用的值明确了哪些问题)。这绝对应该被重构,我这样做是为了说明每个需求是如何被满足的。

    Imports System.Security.Cryptography
    Imports System.IO
    Imports System.Text
    Imports System.Security.Cryptography.X509Certificates
    
    Public Class SoAnswer
        Dim keySize As Integer = 128
        Public Function EncryptData() As XDocument
            Dim encoder As UTF8Encoding = New UTF8Encoding()
            'Specifed Root Name in Declaration
            Dim outputDocument As XDocument = New XDocument(New XElement("SECURE_REQUEST_GROUP"))
            outputDocument.Declaration = New XDeclaration("1.0", "utf-8", "true")
            'outputDocument.Root.Name = "Whatever they specify the root of the xml should be"
            Dim riXml As XDocument
            Dim file As FileStream = New FileStream("C:\routingdoc.xml", FileMode.Open, FileAccess.Read)
            riXml = XDocument.Load(file)
    
            Dim symKey As Byte() = Requirement1(keySize)
            Dim encryptedXml As Byte() = Requirement2(encoder.GetBytes(riXml.ToString()), symKey)
            Dim encodedXml = Requirement3(encryptedXml)
            'Moved Requirement 4 below requirement 9 so it will appear below the key in the output XML
            'Requirement4(encodedXml, outputDocument)
            Dim hash As Byte() = Requirement5(riXml)
            Dim hashKey = Requirement6(hash, symKey)
            Dim encryptedHashKey = Requirement7(hashKey)
            Dim encodedHashKey = Requirement8(encryptedHashKey)
            Requirement9(encodedHashKey, outputDocument)
            Requirement4(encodedXml, outputDocument)
            'Now you should have an XDocument with the proper content to POST to the web service
    
            'Decrypt check
            Dim check As String = encoder.GetString(Decrypt(Convert.FromBase64String(encodedXml), symKey))
    
           postStaticTestXML(outputDocument.ToString)
        End Function
    
        Private Function Requirement1(size As Integer) As Byte()
            Using aes As New AesCryptoServiceProvider()
                aes.KeySize = size
                aes.GenerateKey()
                Return aes.Key
            End Using
        End Function
    
        Private Function Requirement2(data() As Byte, key() As Byte) As Byte()
            Using aes As New AesCryptoServiceProvider()
                Dim iv As Byte() = aes.IV
                Using encryptor As ICryptoTransform = aes.CreateEncryptor(key, iv)
                    Using msEncrypt As MemoryStream = New MemoryStream()
                        Using csEncrypt As CryptoStream = New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
                            csEncrypt.Write(data, 0, data.Length)
                            csEncrypt.FlushFinalBlock()
                            Dim encryptedData As Byte() = msEncrypt.ToArray()
                            Dim buffer(iv.Length + encryptedData.Length - 1) As Byte
                            buffer = CombineArrays(iv, encryptedData)
                            Return buffer
                        End Using
                    End Using
                End Using
            End Using
        End Function
    
        Private Function Requirement3(content As Byte()) As String
            Return Convert.ToBase64String(content)
        End Function
    
        Private Sub Requirement4(content As String, ByRef doc As XDocument)
        'added XAttribute to accommodate the required algorithm attribute
            doc.Root.Add(New XElement("ENCRYPTED_RI", content, New XAttribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#aes128-cbc")))
        End Sub
    
        Private Function Requirement5(content As XDocument) As Byte()
            Dim encoder As UTF8Encoding = New UTF8Encoding()
            Using hash As New SHA1CryptoServiceProvider()
                Return hash.ComputeHash(encoder.GetBytes(content.ToString()))
            End Using
        End Function
    
        Private Function Requirement6(hash As Byte(), key As Byte()) As Byte()
            Return CombineArrays(hash, key)
        End Function
    
        Private Function Requirement7(content As Byte()) As Byte()
            'I'm assuming here that they originally sent you a .cer file with their private key in it
            'Dim cert As X509Certificate2 = X509Certificate2.CreateFromCertFile("path\filename of .cer file")
            'X509Certificate2 Could not be directly specified with CreateFromCertFile. A new instance was created and set to derive its value from the retrieved X509Certificate
            Dim cert As X509Certificate2 = New X509Certificate2(X509Certificate.CreateFromCertFile("C:\cert-1.txt"))
            Using rsa As RSACryptoServiceProvider = cert.PublicKey.Key
                'This assumes PKCS7 padding which is most common
                Return rsa.Encrypt(content, False)
            End Using
        End Function
    
        Private Function Requirement8(content As Byte()) As String
            Return Convert.ToBase64String(content)
        End Function
    
        Private Sub Requirement9(content As String, ByRef doc As XDocument)
        'Added XAttribute to accommodate for the required "Algorithm" attribute
            doc.Root.Add(New XElement("ENCRYPTED_KEY", content, New XAttribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-1_5")))
        End Sub
    
        'Support function
        Private Function CombineArrays(array1 As Byte(), array2 As Byte())
            Dim buffer(array1.Length + array2.Length - 1) as Byte
            System.Buffer.BlockCopy(array1, 0, buffer, 0, array1.Length)
            System.Buffer.BlockCopy(array2, 0, buffer, array1.Length, array2.Length)
            Return buffer
        End Function
    
        Private Function Decrypt(data() As Byte, key() As Byte) As Byte()
            Dim iv((128 / 8) - 1) As Byte
            Buffer.BlockCopy(data, 0, iv, 0, iv.Length)
            Dim value(data.Length - iv.Length - 1) As Byte
            Buffer.BlockCopy(data, iv.Length, value, 0, value.Length)
            Using aes As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                Using decryptor As ICryptoTransform = aes.CreateDecryptor(key, iv)
                    Using msDecrypt As MemoryStream = New MemoryStream(value)
                        Using csDecrypt As CryptoStream = New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
                            Dim decrypted(msDecrypt.Length - 1) As Byte
                            csDecrypt.Read(decrypted, 0, decrypted.Length)
                            Return RemovePadding(decrypted)
                        End Using
                    End Using
                End Using
            End Using
        End Function
    
        Private Function RemovePadding(data As Byte()) As Byte()
            Dim trimCount As Integer = 0
            For i As Integer = data.Length - 1 To data.Length - (128 / 8) + 1 Step -1
                If data(i) = 0 Then trimCount += 1 Else Exit For
            Next
    
            If trimCount <= 0 Then Return data
    
            Dim buffer((data.Length - trimCount) - 1) As Byte
            System.Buffer.BlockCopy(data, 0, buffer, 0, buffer.Length)
            Return buffer
        End Function
    
    End Class
    
     类似资料:
    • 问题内容: 我有一个关于在AES加密中使用初始化向量的问题。我引用以下文章/帖子将加密功能构建到程序中: [1] 基于Java256位AES密码的加密 [2]http://gmailassistant.sourceforge.net/src/org/freeshell/zs/common/Encryptor.java.html 我最初从第一个链接开始关注erickson的解决方案,但是据我所知,我

    • 我使用初始化向量和填充实现了AES 128位加密,如下面的代码所示。我碰巧使用了ColdFusion,但我认为这并不重要。加密结果显示了一些重复模式,这是我没有预料到的,但话说回来,我不知道正确输出的特征。我是否正确地进行了初始化向量和填充? 下面是示例输出: 每个加密字符串都以相同的21个字符结尾: 当原始字符串相同(第3和第4个示例中的“String3”)时,EncryptedString以相

    • 我只需要通过代码加密AES CBC 128位模式的字符串。我使用openssl库完成了这项工作,但无法获得正确的输出。 到目前为止,我已经完成了。 我的十六进制输出是:B0 15 751B50 80 D4 FF 81 68 146BB71B95 99 37 38 但正确的输出是:< code > 73 5C 04 F9 57 18 43 7C EE 68 27 59 2B 41 A8 DA (通过

    • 我最近在Java中使用了AES CBC 128算法来加密数据。现在我需要用PHP重建算法,但我不知道如何重建,因为互联网上的PHP算法返回不同的结果。也许你能帮我。 这是要加密的Java代码: 这是我的php代码: 当我从java加密加密数据时,此结果无法在Php解密上解密。 你们能帮我构建一个PHP脚本吗?它可以返回与java加密相同的结果?

    • 我正在尝试在运行FreeRTOS的微处理器上使用mbedTLS加密一些文本。我正在使用带有PKCS7填充的AES 128 CBC。如果我尝试在mbedTLS中加密,并在文本少于16个字符时在Java中解密,则可以正常工作。我可以在Java中解密它,并且文本匹配。如果它更长,那么它就不再有效。我做错了什么? mbedTLS 代码: Java代码: Java抛出javax.crypto。BadPadd

    • 在从Delphi2007迁移到XE2的过程中,我们正在考虑将加密库从DCPCrypt切换到Turbopower Lockbox 3。 a) 在DCPCrypt中,我可以显式控制初始化向量。如何在TPLB3中设置IV? b)DCPCrypt没有填充,我们在加密前用零填充明文。TPLB垫如何?当然,我们仍然可以自己做。 密码=AES-256; 链接模式=CBC; 终止=C#样式全零填充; IV传输=在