C# 如何使用“System.Security.Cryptography.AesManaged”来加密一个字节[]?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/967773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:26:49  来源:igfitidea点击:

How to use 'System.Security.Cryptography.AesManaged' to encrypt a byte[]?

c#encryptioncryptography

提问by Chris

Basically i want to use System.Security.Cryptography.AesManaged (or a better class, if you think there is one?) to take one byte array and create another encrypted byte array, using a given symmetric key (i assume i'll need one?).

基本上我想使用 System.Security.Cryptography.AesManaged(或者更好的类,如果你认为有一个?)来获取一个字节数组并创建另一个加密字节数组,使用给定的对称密钥(我假设我需要一?)。

I also will need the way to reverse this procedure.

我还需要扭转这个过程的方法。

The point of this is so i can encrypt stored passwords. I assume there's a simple way to do this?

这样做的重点是我可以加密存储的密码。我认为有一种简单的方法可以做到这一点?

Thanks

谢谢

回答by Eugene Yokota

Simple encrypting and decrypting data in C#.

在 C# 中简单地加密和解密数据

Edit: For passwords, I would recommend using BCryptinstead of doing a two-way encryption, unless you really need to recover the original password. Normally you just need the fact that someone knew the password, not the password itself.

编辑:对于密码,我建议使用BCrypt而不是进行双向加密,除非您确实需要恢复原始密码。通常,您只需要有人知道密码的事实,而不是密码本身。

回答by Michael Petrotta

EDIT: Noticed eed3si9n's edit... I agree, symmetric encryption is a bad choice for passwords. Use hashes (and notMD5) instead. Here's a very complete example.

编辑:注意到 eed3si9n 的编辑...我同意,对称加密对于密码来说是一个糟糕的选择。改用哈希(而不是MD5)。这是一个非常完整的例子

A simple example:

一个简单的例子:

byte[] clear = GetCleartext();
HashAlgorithm sha2 = SHA256CryptoServiceProvider.Create();
byte[] hashed = sha2.ComputeHash(clear);

To validate a correct password, you would run the same computation over the provided password, and compare the result to the hash you have in your database.

要验证正确的密码,您将对提供的密码运行相同的计算,并将结果与​​数据库中的哈希值进行比较。

It's good practice to add salt (random data) to the cleartext to avoid rainbow table attacks. Basically, append a known randomly-generated value, unique to that user, to the cleartext before hashing.

向明文添加盐(随机数据)以避免彩虹表攻击是一种很好的做法。基本上,在散列之前将一个已知的随机生成的值附加到该用户唯一的明文中。

回答by Chris

Here's what i did in the end, inspired by (an older version of) michael's answer:

这是我最终所做的,受到(旧版本)迈克尔回答的启发:

private string Encrypt(string input)
{
  return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input)));
}
private byte[] Encrypt(byte[] input)
{
  PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 });
  MemoryStream ms = new MemoryStream();
  Aes aes = new AesManaged();
  aes.Key = pdb.GetBytes(aes.KeySize / 8);
  aes.IV = pdb.GetBytes(aes.BlockSize / 8);
  CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
  cs.Write(input, 0, input.Length);
  cs.Close();
  return ms.ToArray();
}
private string Decrypt(string input)
{
  return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input)));
}
private byte[] Decrypt(byte[] input)
{
  PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 });
  MemoryStream ms = new MemoryStream();
  Aes aes = new AesManaged();
  aes.Key = pdb.GetBytes(aes.KeySize / 8);
  aes.IV = pdb.GetBytes(aes.BlockSize / 8);
  CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write);
  cs.Write(input, 0, input.Length);
  cs.Close();
  return ms.ToArray();
}

回答by Walter Stabosz

There is a pretty nice C# implementation of symmetric key encryption at http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx. It supports AES, Triple DES, and Rijndael. It has easy to follow functions in the form:

http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx 上有一个非常好的对称密钥加密的 C# 实现。它支持 AES、三重 DES 和 Rijndael。它具有以下形式的易于遵循的功能:

 string Encrypt(string plaintext, string password, string salt)

回答by bkrakower

The OP states they have to pass the credentials to another service, which is a completely different issue than password storage and verification.

OP 声明他们必须将凭据传递给另一个服务,这与密码存储和验证完全不同。

Depending on how much control you have over the partner service, or what they expose, the best solutions involve a vendor provided or industry standard approaches such as Kerberos, SAML or other stable, secure bearer token means to flow trust. This is a deep topic.

根据您对合作伙伴服务的控制程度或它们公开的内容,最佳解决方案涉及供应商提供的或行业标准方法,例如 Kerberos、SAML 或其他稳定、安全的承载令牌方法来传递信任。这是一个很深的话题。

But let's assume you need to pass credentials via Basic Auth SSL/TLS. So now you need to store them securely in a reversible manner. To solve this problem, I have had success with the secret key being conveyed using a certificate private key. This affords some protection of your secret by the operating system and allows for OPS folks to manage the keys, which is desirable. The account used to run your process must be granted rights to see the private key, which then terminates the trust chain at the OS.

但让我们假设您需要通过 Basic Auth SSL/TLS 传递凭据。所以现在您需要以可逆的方式安全地存储它们。为了解决这个问题,我已经成功地使用证书私钥传输了密钥。这通过操作系统为您的秘密提供了一些保护,并允许 OPS 人员管理密钥,这是可取的。用于运行您的进程的帐户必须被授予查看私钥的权限,然后在操作系统中终止信任链。

You still might have to think about key rotation, which will require you to store a version number with the cipher text.

您可能仍然需要考虑密钥轮换,这将要求您存储带有密文的版本号。

Also, SecureString might be of interest, but until all .NET API's allow SecureString to be passed as part of a credential, often times you end up with a string on the managed heap you cannot destroy.

此外,可能对 SecureString 感兴趣,但直到所有 .NET API 都允许将 SecureString 作为凭证​​的一部分传递之前,通常您最终会在托管堆上得到一个无法销毁的字符串。

Anyway, this isn't a spoon fed answer with code, but from experience, I have found that managing the chain of secrets is always a problem, and if you cannot terminate at a hardened infrastructure such as Active Directory, certificates are the next best thing.

无论如何,这不是带有代码的勺子式答案,但根据经验,我发现管理秘密链始终是一个问题,如果您不能在诸如 Active Directory 之类的强化基础设施上终止,则证书是次优的事物。