首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据加密/解密

数据加密/解密
EN

Code Review用户
提问于 2011-12-09 18:42:40
回答 2查看 2.5K关注 0票数 5

我试着处理一些数据的加密/解密。让它和缓冲区一起工作对我来说是一项艰苦的工作。

这是我想出的代码:

代码语言:javascript
复制
public static string Encrypt(string dataToEncrypt, byte[] publicKeyInfo)
{
    //// Our bytearray to hold all of our data after the encryption
    byte[] encryptedBytes = new byte[0];
    using (var rsa = new RSACryptoServiceProvider())
    {
        try
        {
            var encoder = new UTF8Encoding();

            byte[] encryptThis = encoder.GetBytes(dataToEncrypt);

            //// Importing the public key
            rsa.ImportCspBlob(publicKeyInfo);

            int blockSize = (rsa.KeySize / 8) - 32;

            //// buffer to write byte sequence of the given block_size
            byte[] buffer = new byte[blockSize];

            byte[] encryptedBuffer = new byte[blockSize];

            //// Initializing our encryptedBytes array to a suitable size, depending on the size of data to be encrypted
            encryptedBytes = new byte[encryptThis.Length + blockSize - (encryptThis.Length % blockSize) + 32];

            for (int i = 0; i < encryptThis.Length; i += blockSize)
            {
                //// If there is extra info to be parsed, but not enough to fill out a complete bytearray, fit array for last bit of data
                if (2 * i > encryptThis.Length && ((encryptThis.Length - i) % blockSize != 0))
                {
                    buffer = new byte[encryptThis.Length - i];
                    blockSize = encryptThis.Length - i;
                }

                //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                if (encryptThis.Length < blockSize)
                {
                    buffer = new byte[encryptThis.Length];
                    blockSize = encryptThis.Length;
                }

                //// encrypt the specified size of data, then add to final array.
                Buffer.BlockCopy(encryptThis, i, buffer, 0, blockSize);
                encryptedBuffer = rsa.Encrypt(buffer, false);
                encryptedBuffer.CopyTo(encryptedBytes, i);
            }
        }
        catch (CryptographicException e)
        {
            Console.Write(e);
        }
        finally
        {
            //// Clear the RSA key container, deleting generated keys.
            rsa.PersistKeyInCsp = false;
        }
    }
    //// Convert the byteArray using Base64 and returns as an encrypted string
    return Convert.ToBase64String(encryptedBytes);
}




public static string Decrypt(string dataToDecrypt, byte[] privateKeyInfo)
{
    //// The bytearray to hold all of our data after decryption
    byte[] decryptedBytes;

    //Create a new instance of RSACryptoServiceProvider.
    using (var rsa = new RSACryptoServiceProvider())
    {
        try
        {
            byte[] bytesToDecrypt = Convert.FromBase64String(dataToDecrypt);

            //// Import the private key info
            rsa.ImportCspBlob(privateKeyInfo);

            //// No need to subtract padding size when decrypting
            int blockSize = rsa.KeySize / 8;

            //// buffer to write byte sequence of the given block_size
            byte[] buffer = new byte[blockSize];

            //// buffer containing decrypted information
            byte[] decryptedBuffer = new byte[blockSize];

            //// Initializes our array to make sure it can hold at least the amount needed to decrypt.
            decryptedBytes = new byte[dataToDecrypt.Length];

            for (int i = 0; i < bytesToDecrypt.Length; i += blockSize)
            {
                if (2 * i > bytesToDecrypt.Length && ((bytesToDecrypt.Length - i) % blockSize != 0))
                {
                    buffer = new byte[bytesToDecrypt.Length - i];
                    blockSize = bytesToDecrypt.Length - i;
                }

                //// If the amount of bytes we need to decrypt isn't enough to fill out a block, only decrypt part of it
                if (bytesToDecrypt.Length < blockSize)
                {
                    buffer = new byte[bytesToDecrypt.Length];
                    blockSize = bytesToDecrypt.Length;
                }

                Buffer.BlockCopy(bytesToDecrypt, i, buffer, 0, blockSize);
                decryptedBuffer = rsa.Decrypt(buffer, false);
                decryptedBuffer.CopyTo(decryptedBytes, i);
            }
        }
        finally
        {
            //// Clear the RSA key container, deleting generated keys.
            rsa.PersistKeyInCsp = false;
        }
    }

    //// We encode each byte with UTF8 and then write to a string while trimming off the extra empty data created by the overhead.
    var encoder = new UTF8Encoding();
    return encoder.GetString(decryptedBytes).TrimEnd(new[] { '\0' });

}

我试着看看我是否能把它分开,但在我的努力下,我想出了一个我认为更复杂的方法(更高的圈复杂度)。我突然有很多if语句,必须处理加密模式,但也需要处理来自UTF8或BASE64的编码。

EN

回答 2

Code Review用户

回答已采纳

发布于 2011-12-10 10:44:46

我对密码学方面没有任何评论,但我有几个一般的编程要点:

  • 没有必要为内联注释设置四个正斜杠字符,您只需要两个。
  • 没有必要将您的encryptedBytes数组初始化为空数组,因为您稍后会重新初始化它。
  • 您应该使用System.Text.Encoding.UTF8而不是手动实例化UTF8Encoding
  • 为了便于阅读(初始化encryptedBytes数组时的第24行和检查“要解析的额外信息”的第29行),可能值得在条件和数组构建中拆分内联计算。
  • 虽然我鼓励使用好位置注释来解释算法或程序步骤(特别是当它是一个复杂的算法时),但我认为您在某些地方可能有些过分。因此,可能需要删除更明显的注释,例如“我们的字节数组在加密后保存我们所有的数据”--变量的名称已经表明了这一点。这不是一个重点,但它将有助于您的方法的长度。
  • 关于异常处理,我建议在您到达catch子句时结束代码执行,因为如果程序失败,您不希望程序继续执行该算法。此外,我建议将try子句中的代码再分解一些,这样您就只能在可能导致CryptographicException的确切行周围设置try-catch块。这并不重要,但它可以帮助另一位读者很容易地识别出可能出现问题的台词(S)。

除了上述要点之外,代码本身看起来结构也相当好,而且符合逻辑。

票数 4
EN

Code Review用户

发布于 2011-12-09 21:28:31

在欧洲央行模式下,你使用RSA作为分组密码。它通常不是这样使用的。除非您有很好的理由这样做,否则您应该只进行一个RSA加密,一个分组密码的安全随机密钥(即AES),然后使用该密钥对您的消息进行加密。

由于您正在将string转换为string,很明显,内存和延迟都不是问题,所以您可以通过使用MemoryStreamCryptoStream来避免与byte[]s打交道。您还可以使用Encoding.UTF8稍微简化en/解码步骤。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/6662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档