简体   繁体   English

如何使用特定的密钥解密加密的字符串

[英]How to Decrypt an Encrypted String using a specific Key

First of all this is my code so far. 首先,这是到目前为止的代码。

public Form1()
{
    InitializeComponent();
    desObj = Rijndael.Create();
}

string cData;
byte[] cBytes;
byte[] pBytes;
byte[] pBytes2;
byte[] pKey;
SymmetricAlgorithm desObj;

public static string InputBox(string title, string promptText)
{
    Form form = new Form();
    Label label = new Label();
    TextBox textBox = new TextBox();
    Button buttonOk = new Button();
    Button buttonCancel = new Button();

    form.Text = title;
    label.Text = promptText;

    buttonOk.Text = "OK";
    buttonCancel.Text = "Cancel";
    buttonOk.DialogResult = DialogResult.OK;
    buttonCancel.DialogResult = DialogResult.Cancel;

    label.SetBounds(9, 20, 372, 13);
    textBox.SetBounds(12, 36, 372, 20);
    buttonOk.SetBounds(228, 72, 75, 23);
    buttonCancel.SetBounds(309, 72, 75, 23);

    label.AutoSize = true;

    textBox.MaxLength = 16;
    textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
    buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
    buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

    form.ClientSize = new Size(396, 107);
    form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
    form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
    form.FormBorderStyle = FormBorderStyle.FixedDialog;
    form.StartPosition = FormStartPosition.CenterScreen;
    form.MinimizeBox = false;
    form.MaximizeBox = false;
    form.AcceptButton = buttonOk;
    form.CancelButton = buttonCancel;
    DialogResult dR = form.ShowDialog();
    string test = textBox.Text;
    MessageBox.Show("test: "+test);
    if (test.Length != 16)
    {
        int pKey2NeededLength = 0;
        for (int i = 0; i < (test.Length + 16); i++)
        {
            if ((i + test.Length) == 16)
            {
                pKey2NeededLength = i;
                MessageBox.Show("pKey2NeededLength: "+pKey2NeededLength);
                break;
            }
        }
        StringBuilder sB = new StringBuilder();
        string[] pArray = { "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678", "123456789", "1234567891", "12345678912", "123456789123", "1234567891234", "12345678912345", "123456789123456", "1234567891234567" };
        sB.Append(test + pArray[pKey2NeededLength - 1]);
        test = sB.ToString();
        MessageBox.Show("test(after sB): "+test);
    }
    return test;
}

private void button1_Click(object sender, EventArgs e)//ENCRYPT
{
    cData = richTextBox1.Text;
    pBytes = Encoding.ASCII.GetBytes(cData);
    string pKey2 = InputBox("Encryption-Key", "Enter a Encryption-Key:");
    pKey = Encoding.ASCII.GetBytes(pKey2);
    desObj.Key = pKey;
    desObj.Mode = CipherMode.CBC;
    desObj.Padding = PaddingMode.PKCS7;
    System.IO.MemoryStream mS = new System.IO.MemoryStream();
    CryptoStream cS = new CryptoStream(mS, desObj.CreateEncryptor(), CryptoStreamMode.Write);
    cS.Write(pBytes, 0, pBytes.Length);
    cS.Close();
    cBytes = mS.ToArray();
    mS.Close();
    richTextBox1.Text = Encoding.ASCII.GetString(cBytes);
}

private void button2_Click(object sender, EventArgs e)//DECRYPT
{
    string pKey3 = InputBox("Decryption-Key", "Enter a Decryption-Key:");
    MessageBox.Show("pKey3: "+pKey3);
    byte[] pBytes3 = Encoding.ASCII.GetBytes(pKey3);
    MessageBox.Show("pBytes3: "+pBytes3);
    System.IO.MemoryStream mS1 = new System.IO.MemoryStream(pBytes3/*cBytes*/);
    CryptoStream cS1 = new CryptoStream(mS1, desObj.CreateDecryptor(), CryptoStreamMode.Read);
    cS1.Read(pBytes3/*cBytes*/, 0, pBytes3/*cBytes*/.Length);
    pBytes2 = mS1.ToArray();
    cS1.Close();
    mS1.Close();
    richTextBox1.Text = Encoding.ASCII.GetString(pBytes2);
}

Now what i'm trying to do: My programm has 1 richTextBox and 2 buttons one button is for encrypting the text of the textbox and the other one for decrypting it. 现在我要做什么:我的程序有1个richTextBox和2个按钮,一个按钮用于加密文本框的文本,另一个按钮用于解密文本框。 So if you press the encrypt-button you are asked for a Key(maximum characters: 16), if your entered key has a lower number of characters than 16, it gets filled up, fe "test" becomes "test123456789123". 因此,如果您按下加密按钮,则会要求您输入密钥(最大字符数:16),如果您输入的密钥的字符数少于16,则该字符将被填满,fe“ test”将变为“ test123456789123”。 The encrypting part workes so far, but i'm having troubles with decrypting it. 到目前为止,加密部分已经可以使用,但是我在解密时遇到了麻烦。 if you press the decrypting-button you are asked to enter a key too, and it gets also filled up, so test becomes the same 16character-key like above. 如果您按下解密按钮,也会要求您输入密钥,并且密钥也被填满,因此测试将变成与上述相同的16个字符的密钥。 But after i have entered "test" it gives me the following error: 但是在我输入“测试”之后,它给了我以下错误:

An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll mscorlib.dll中发生了类型为'System.Security.Cryptography.CryptographicException'的未处理异常

Additional information: Character spacing are invalid and can not be removed . 附加信息:字符间距无效,不能删除。

Hopefully somebody knows what to do! 希望有人知道该怎么做! Thanks in advance :) 提前致谢 :)

EDIT: So this works decrypting the encrypted text: 编辑:所以这可以解密加密的文本:

private void button2_Click(object sender, EventArgs e)//DECRYPT
{
    //string pKey3 = InputBox("Decryption-Key", "Enter a Decryption-Key:");
    System.IO.MemoryStream mS1 = new System.IO.MemoryStream(cBytes);
    CryptoStream cS1 = new CryptoStream(mS1, desObj.CreateDecryptor(), CryptoStreamMode.Read);
    cS1.Read(cBytes, 0, cBytes.Length);
    pBytes2 = mS1.ToArray();
    cS1.Close();
    mS1.Close();
    string garbage = Encoding.ASCII.GetString(pBytes2);
    string decrypt = garbage.Substring(0, pBytes.Length);
    richTextBox1.Text = decrypt;
}

but this only works directly after formating and not when i close the programm and open it again, so i want to get the text in the textbox and decrypt it after the string that is entered as decryption key in this case pKey3 ! 但这仅在格式化后直接起作用,而不是在我关闭程序并再次打开时起作用,因此在这种情况下,我想获取文本框中的文本并在作为解密密钥输入的字符串之后解密它pKey3

The code above doesn't store and then restore the IV value. 上面的代码不会存储然后恢复IV值。 The IV value will be randomized upon first use of the desObj . IV值将在首次使用desObj随机化。 So if the ciphertext is directly decrypted with the same object instance the IV will still be set correctly. 因此,如果密文是使用相同的对象实例直接解密的,则IV仍将正确设置。 If you re-instantiate the object it won't be. 如果重新实例化该对象,则不会。 Usually the IV is stored together with the ciphertext. 通常,IV与密文一起存储。

Furthermore, the above code seems to store the cihpertext as ASCII. 此外,以上代码似乎将cihpertext存储为ASCII。 Ciphertext bytes may have any value, including the bottom 32 unprintable ones and value 127 which is reserved. 密文字节可以具有任何值,包括底部的32个不可打印的字节和保留的值127。 Instead the ciphertext should be encoded as base 64. Information may be lost when decoding the bytes to ASCII. 而是应将密文编码base64 。将字节解码为ASCII时,信息可能会丢失。

Notes: 笔记:

  • you should use a PBKDF such as PBKDF2 to derive a key from a password. 您应该使用PBKDF(例如PBKDF2)从密码派生密钥。 Directly using a password as key is not secure 直接使用密码作为密钥是不安全的
  • single DES or double key triple DES is not considered secure anymore, better upgrade to AES and think about adding an authentication tag (MAC) over your IV and ciphertext 单DES或双密钥三DES不再被认为是安全的,可以更好地升级到AES,并考虑在IV和密文上添加身份验证标签(MAC)

I noticed on first look that you get password during decryption but you use it as content in MemoryStream. 乍一看,我注意到您在解密过程中获得了密码,但是您将其用作MemoryStream中的内容。 Because you have password already set in encryption method, it looks like that you tried decrypt entered password with encryption password. 由于您已经在加密方法中设置了密码,因此您似乎尝试使用加密密码解密输入的密码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM