11

我需要加密一个字符串,然后才能再次解密它。

我在这里实现了解决方案并且效果很好,但是生成的字符串不合适,因为它需要简单且足够短以供用户使用。

我正在加密递增的数据库 ID(从 1 开始)并且不会超过 500。理想情况下,我希望加密字符串的长度不超过 6 个字符。

任何想法表示赞赏..

编辑:这是一个冗长的表格,用户可以在以后使用此生成的字符串恢复

4

4 回答 4

8

您可以在CTR 模式下使用 AES,无需任何填充。在这种模式下,有一个计数器被加密,然后结果与你的明文进行异或,即数字。结果应该很小,并且您将获得 AES 的加密,这将比您使用的任何替代密码更好(您可能会手动破解)。您将必须获得BouncyCastle 加密库,但是因为Rijndael的 Microsoft 实施没有 CTR 作为可用模式。下面是您需要实现的 AES 类的示例。以及加解密的例子。

using System;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

public class AES
{
    private readonly Encoding encoding;

    private SicBlockCipher mode;


    public AES(Encoding encoding)
    {
        this.encoding = encoding;
        this.mode = new SicBlockCipher(new AesFastEngine());
    }

    public static string ByteArrayToString(byte[] bytes)
    {
        return BitConverter.ToString(bytes).Replace("-", string.Empty);
    }

    public static byte[] StringToByteArray(string hex)
    {
        int numberChars = hex.Length;
        byte[] bytes = new byte[numberChars / 2];

        for (int i = 0; i < numberChars; i += 2)
        {
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        }

        return bytes;
    }


    public string Encrypt(string plain, byte[] key, byte[] iv)
    {
        byte[] input = this.encoding.GetBytes(plain);

        byte[] bytes = this.BouncyCastleCrypto(true, input, key, iv);

        string result = ByteArrayToString(bytes);

        return result;
    }


    public string Decrypt(string cipher, byte[] key, byte[] iv)
    {
        byte[] bytes = this.BouncyCastleCrypto(false, StringToByteArray(cipher), key, iv);

        string result = this.encoding.GetString(bytes);

        return result;
    }


    private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, byte[] key, byte[] iv)
    {
        try
        {
            this.mode.Init(forEncrypt, new ParametersWithIV(new KeyParameter(key), iv));

            BufferedBlockCipher cipher = new BufferedBlockCipher(this.mode);

            return cipher.DoFinal(input);
        }
        catch (CryptoException)
        {
            throw;
        }
    }
}

示例用法

string test = "1";

AES aes = new AES(System.Text.Encoding.UTF8);

RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
byte[] key = new byte[32];
byte[] iv = new byte[32];

// Generate random key and IV
rngCsp.GetBytes(key);
rngCsp.GetBytes(iv);

string cipher = aes.Encrypt(test, key, iv);

string plaintext = aes.Decrypt(cipher, key, iv);

Response.Write(cipher + "<BR/>");

Response.Write(plaintext);

输出示例

CB
1 
于 2012-11-08T21:21:19.927 回答
3
//encryption   
string output="";   
char[] readChar = yourInput.ToCharArray();   
for (int i = 0; i < readChar.Length; i++)  
{   
    int no = Convert.ToInt32(readChar[i]) + 10;   
    string r = Convert.ToChar(no).ToString();   
    output+=r;   
}  
//decryption  
string output="";   
char[] readChar = yourInput.ToCharArray();   
for (int i = 0; i < readChar.Length; i++)   
{   
    int no = Convert.ToInt32(readChar[i]) - 10;   
    string r = Convert.ToChar(no).ToString();   
    output+=r;   
}
于 2012-11-08T20:31:39.763 回答
1

if you want it to be simple maybe use a main key of 6 letter add it to the 6 letters input do a modulo based on the allowed input chars

its like a =1

b =2

c = 3

and then simply add a number a + 13 mod 24 > ...

wont say its secure but its simple as you requested You might also do some combinations like for the next char is deoded prev char as +xx

于 2012-11-08T19:58:28.423 回答
0

既然您说这些是递增的数据库 ID,我假设我们正在谈论正整数。限制加密确实不是一个好主意,因为加密越有限,就越容易破解。我不确定您的目标,但听起来您可能只想通过“加密”来隐藏最终用户的 ID。所以,如果我假设这些是 1 到 999 之间的正整数,那么我的建议如下。一,简单的字符替换。这将很容易弄清楚,因为您将被限制为 10 个字符。二,将它们转换为十六进制。不会欺骗很多人,但普通的最终用户可能无法识别它。第三,将数字转换为Base64。这不会像十六进制那样容易被识别。最后的,想出某种公式,您可以将其应用于始终产生唯一结果的数字。但是我真的不建议这样做,因为它非常困难。

于 2012-11-08T20:33:27.863 回答