我已经构建了一个应用程序,可以在其中输入单词或消息并单击密码按钮,这将生成一个随机密钥并加密该消息,然后可以通过单击解密按钮来解密该消息。我的问题是我的保存和打开按钮的新功能我想以RAW加密格式保存一条消息,然后能够打开和解密该消息以及已加密和先前保存的所有其他消息。我的问题是这不起作用,我认为保存按钮可能有问题,因为我还需要保存密钥以及正确解密消息的消息,这只是我尝试过的事情之一,完全解决了这个问题,我们将不胜感激。此外,我使用的密码是凯撒密码
该图像是我正在工作的应用程序的第一阶段的GUI,消息上城的funk正在加密。显然,下面是代码。
编辑-我曾尝试创建一个元组类来解决我的问题,但我只使用过一次不用介意元组类的类,并且在盯着它看了几个小时后直言不讳地讲了一下,我不知道该怎么办工作会有所帮助。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;
using System.IO;
namespace login_form
{
public partial class Main : Form
{
public string cipherText;
public string originalText;
public string DecipherText;
public int key;
public Main()
{
InitializeComponent();
}
public static char cipher(char ch, int key)
{
if (!char.IsLetter(ch))
{
return ch;
}
char d = char.IsUpper(ch) ? 'A' : 'a';
return (char)((((ch + key) - d) % 26) + d);
}
public static string Encipher(string input, int key)
{
string output = string.Empty;
foreach (char ch in input)
output += cipher(ch, key);
return output;
}
public static string Decipher(string input, int key)
{
return Encipher(input, 26 - key);
}
private void Main_Load(object sender, EventArgs e)
{
}
private void btnCipher_Click(object sender, EventArgs e)
{
Random rndNumber = new Random();
tbKey.Text = rndNumber.Next(0, 26).ToString();
originalText = tbWord.Text;
try {
key = Convert.ToInt32(tbKey.Text);
}
catch {
MessageBox.Show("Invalid Input! Please Try Again");
}
cipherText = Encipher(originalText, key);
tbOutput.Text = Convert.ToString(cipherText);
}
private void btnDecipher_Click(object sender, EventArgs e)
{
DecipherText = tbOutput.Text;
string DecipherOutput = Decipher(cipherText, key);
tbDecipheredOutput.Text = Convert.ToString(DecipherOutput);
}
private void btnOpen_Click(object sender, EventArgs e)
{
var fileContent = string.Empty;
var filePath = string.Empty;
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//Get the path of specified file
filePath = openFileDialog.FileName;
//Read the contents of the file into a stream
var fileStream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(fileStream))
{
fileContent = reader.ReadToEnd();
}
}
}
tbOutput.Text = fileContent;
MessageBox.Show("Path of File: " + filePath);//shows the path of the file
}
private void btnSave_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";//the format the file will be saved in
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
saveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);//saves the folder to my documents
string Content = tbOutput.Text;//saves the contens of textbox output
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
File.WriteAllText((saveFileDialog1.FileName), Content);
}
catch (IOException)
{
MessageBox.Show("File Was not Saved");
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace login_form
{
class tuple
{
int key;
string cipherText;
static public void Main()
{
// Creating tuple with two elements
// Using Create method
var My_Tuple = Tuple.Create("lol", 23);
Console.WriteLine("Element 1: " + My_Tuple.Item1);
Console.WriteLine("Element 2: " + My_Tuple.Item2);
}
}
}
与您所做的事情不完全相同,但是在我的加密项目中,我必须将盐(随机的一组比特)与密码哈希存储在一起,以便以后可以验证密码哈希并添加4竖线字符||||在一起。
所以我最后得到一个像[PasswordHash] |||| [Salt]]这样的字符串>
它像这样以二进制数组形式出现:
-加密位示例
ꊧ汴皤雦㇋袭ᆐ||||뷁綊ꮱ⨭쇕ꐱ�
-然后,我对上面的内容进行加密,以便可以将其存储在SQL中以供以后验证。
Z / if9FTkP5dbJvaxsPIhsoX0v7ZyChFr7IdxZ / mAZzqYP7gWi6sVTDOQZw4KcSEJHwv5ThTuQIKGkRItLi1ree82mXdiHc5ru2l92m1zDRc =
这是我在Stack Overflow上遇到麻烦的地方,但是如果可以帮助一个人,我对此表示满意。我有一个开源项目:DataJuggler.Core.Cryptography(.Net Core)
https://github.com/DataJuggler/DataJuggler.Core.Cryptography
我将发布一个课程,如果您需要整个项目,可以查看其余课程:
Nuget:DataJuggler.Core.UltimateHelper
#region using statements
using System;
using System.Text;
using System.Security.Cryptography;
using Konscious.Security.Cryptography;
using System.Linq;
using DataJuggler.UltimateHelper.Core;
using DataJuggler.Core.Cryptography.Objects;
#endregion
namespace DataJuggler.Core.Cryptography
{
#region class CryptographyHelper
/// <summary>
/// This object hands all encryption for this application.
/// </summary>
public class CryptographyHelper
{
#region Private Variables
// We can use a fixed pepper for the PBKDF2 salt.
private static byte[] _pepper = new byte[] { 0x04, 0xC5, 0x02, 0xF8, 0xD3, 0xD4, 0x23, 0xB9 };
public const string DefaultPassword = "NotASecret";
#endregion
#region Methods
#region CreateSalt()
/// <summary>
/// This method creates a byte array to use
/// </summary>
/// <returns></returns>
private static byte[] CreateSalt()
{
// initial value
byte[] buffer = null;
// Create a strong random number generator
using (var rng = new RNGCryptoServiceProvider())
{
buffer = new byte[16];
rng.GetBytes(buffer);
}
// return value
return buffer;
}
#endregion
#region DecryptString(string stringToDecrypt, string password)
/// <summary>
/// Decrypts a string passed in.
/// </summary>
/// <param customerName="stringToDecrypt">String that needs to be deciphered.</param>
/// <param customerName="ProductPassword">Code to unlock this productPassword.</param>
/// <returns></returns>
public static string DecryptString(string stringToDecrypt, string password)
{
// initial value
string decryptedValue = "";
try
{
// if both strings exist
if (TextHelper.Exists(stringToDecrypt, password))
{
var ivAndCiphertext = Convert.FromBase64String(stringToDecrypt);
if (ivAndCiphertext.Length >= 16)
{
var iv = new byte[16];
var ciphertext = new byte[ivAndCiphertext.Length - 16];
Array.Copy(ivAndCiphertext, 0, iv, 0, iv.Length);
Array.Copy(ivAndCiphertext, iv.Length, ciphertext, 0, ciphertext.Length);
using (var aes = AesManaged.Create())
using (var pbkdf2 = new Rfc2898DeriveBytes(password, _pepper, 32767))
{
var key = pbkdf2.GetBytes(32);
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
// create a new Decryptor
using (var aesTransformer = aes.CreateDecryptor())
{
// get a byte array of the plain text
var plaintext = aesTransformer.TransformFinalBlock(ciphertext, 0, ciphertext.Length);
// set the return value
decryptedValue = Encoding.UTF8.GetString(plaintext);
}
}
}
}
}
catch
{
}
// return value
return decryptedValue;
}
#endregion
#region DecryptString(string stringToDecrypt)
/// <summary>
/// This method decrypts a string using the default password.
/// </summary>
/// <param name="stringToDecrypt"></param>
/// <returns></returns>
public static string DecryptString(string stringToDecrypt)
{
// return value
return DecryptString(stringToDecrypt, DefaultPassword);
}
#endregion
#region EncryptString(string stringToEncrypt, string password)
/// <summary>
/// Encrypts a strings passed in using CBC mode and a moderately decent KDF. Does not provide integrity.
/// This method will return a different value every time called, yet will still decrypt correctly.
/// </summary>
/// <param customerName="stringToEncrypt">String to encrypt</param>
/// <param customerName="productPassword">productPassword needed to unlock encrypted string</param>
/// <returns>A new string that must have the same productPassword passed in to unlock.</returns>
public static string EncryptString(string stringToEncrypt, string password)
{
// initial value
string encryptedString = "";
try
{
// if both strings exist
if (TextHelper.Exists(stringToEncrypt, password))
{
// Remember to dispose of types that implement IDisposable - this old code had lots of memory leaks.
using (var aes = AesManaged.Create())
using (var pbkdf2 = new Rfc2898DeriveBytes(password, _pepper, 32767)) // MD5 is insecure as KDF, we use PBKDF2 instead.
using (var rng = new RNGCryptoServiceProvider())
{
var key = pbkdf2.GetBytes(32); // Let's use AES-256.
var iv = new byte[16];
rng.GetBytes(iv); // We always create a new, random IV for each operation.
var plaintext = Encoding.UTF8.GetBytes(stringToEncrypt); // We use UTF8
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = key;
aes.IV = iv;
using (var aesTransformer = aes.CreateEncryptor())
{
var ciphertext = aesTransformer.TransformFinalBlock(plaintext, 0, plaintext.Length);
var ivAndCiphertext = new byte[iv.Length + ciphertext.Length];
Array.Copy(iv, 0, ivAndCiphertext, 0, iv.Length);
Array.Copy(ciphertext, 0, ivAndCiphertext, iv.Length, ciphertext.Length);
encryptedString = Convert.ToBase64String(ivAndCiphertext);
}
}
}
}
catch
{
}
// return value
return encryptedString;
}
#endregion
#region EncryptString(string stringToEncrypt)
/// <summary>
/// Override that uses default password
/// </summary>
/// <param name="stringToEncrypt"></param>
/// <returns></returns>
public static string EncryptString(string stringToEncrypt)
{
return EncryptString(stringToEncrypt, DefaultPassword);
}
#endregion
#region GeneratePasswordHash(string password, int verifyRetries = 0)
/// <summary>
/// This method hashes the password using Konscious.Security.Cryptography's implementation of Argon2.
/// The salt is returned with the password separated by 4 | (pipe characters I think is the name).
/// You can decrypt from the encrypted password hash to determine the passwordhash and salt, but you cannot decrypt from
/// password hash back to the password.
/// This method uses the default password, which is NotASecret.
/// </summary>
/// <param name="password">The password to create a hash for</param>
/// <param name="verifyRetries">If verify retries is above 0, this method will attempt to verify
/// the generated password hash with the same credentials. If it can't be verified, it will retry
/// up until this value for retries count. The value must be between 0 and 3. After 3 it fails.</param>
/// <returns></returns>
public static string GeneratePasswordHash(string password, int verifyRetries = 0)
{
// call the override
return GeneratePasswordHash(password, DefaultPassword, verifyRetries);
}
#endregion
#region GeneratePasswordHash(string password, string keyCode, int verifyRetries = 0)
/// <summary>
/// This method hashes the password using Konscious.Security.Cryptography's implementation of Argon2.
/// The salt is returned with the password separated by 4 | (pipe characters I think is the name).
/// You can decrypt from the encrypted password hash to determine the passwordhash and salt, but you cannot decrypt from
/// password hash back to the password.
/// </summary>
/// <param name="password">The password to create a hash for</param>
/// <param name="keyCode">A keycode string you create that is used to encrypt/decrypt the password hash
/// after it is created. You can decrypt from the encrypted password hash to determine the passwordhash and salt, but you cannot decrypt from
/// password hash back to the password.
/// </param>
/// <param name="verifyRetries">If verify retries is above 0, this method will attempt to verify
/// the generated password hash with the same credentials. If it can't be verified, it will retry
/// up until this value for retries count. The value must be between 0 and 3. After 3 it fails.</param>
/// <returns></returns>
public static string GeneratePasswordHash(string password, string keyCode, int verifyRetries = 0)
{
// get the passwordHash
string passwordHash = null;
// local
bool verified = false;
// if the password exists
if (TextHelper.Exists(password, keyCode))
{
// get the passwordHash
passwordHash = HashPart1(password, keyCode);
// it will only try up to 3 times, then it bails
if ((verifyRetries > 0) && (verifyRetries <= 3))
{
// try up to 3 times if verifyRetries is set to 3
for (int x = 0; x < verifyRetries; x++)
{
// if all 3 strings exist
if (TextHelper.Exists(password, password, keyCode))
{
// does
verified = VerifyHash(password, keyCode, passwordHash);
}
// if the value for verified is true
if (verified)
{
// break out of the loop
break;
}
// get the passwordHash (again)
passwordHash = HashPart1(password, keyCode);
}
// if not veriified
if (!verified)
{
// password hash could not be created
passwordHash = "";
}
}
}
// return value
return passwordHash;
}
#endregion
#region HashPart1(string password, string keyCode)
/// <summary>
/// This method is used to call some portions of the GeneratePasswordHash
/// multiple times.
/// </summary>
/// <param name="part1"></param>
/// <param name="keyCode"></param>
/// <returns></returns>
private static string HashPart1(string password, string keyCode)
{
// initial value
string part1 = "";
try
{
// Update 1.0.9 create the salt every time as the salt might be the problem (?)
byte[] salt = CreateSalt();
// get the byte array
byte[] passwordBits = HashPassword(password, salt);
// create the hashInfo
PasswordHashInfo hashInfo = new PasswordHashInfo(passwordBits, salt);
// get the hashInfo
string partI = hashInfo.ToString();
// set the return value
part1 = EncryptString(partI, keyCode);
}
catch (Exception error)
{
// for debugging only for now, I may return a response one day
DebugHelper.WriteDebugError("HashPart1", "CryptographyHelper", error);
// explicit set to null
part1 = "";
}
// return value
return part1;
}
#endregion
#region HashPassword(string password, byte[] salt)
/// <summary>
/// Hash this password
/// </summary>
/// <param name="password"></param>
/// <param name="keyCode"></param>
/// <param name="salt"></param>
/// <returns></returns>
private static byte[] HashPassword(string password, byte[] salt)
{
// initial value
byte[] hash = null;
// if all 3 strings exist
if (TextHelper.Exists(password))
{
// Create a new instance of an 'Argon2id' object.
var argon2 = new Argon2id(Encoding.Unicode.GetBytes(password));
argon2.Salt = salt;
argon2.DegreeOfParallelism = 8; // four cores
argon2.Iterations = 2;
argon2.MemorySize = 1024 * 1024; // 1 GB
// get the hash
hash = argon2.GetBytes(16);
}
// return value
return hash;
}
#endregion
#region VerifyHash(string userTypedPassword, string storedPasswordHash)
/// <summary>
/// This method is used to verify the Hash created is the same as a hash stored in the database.
/// This method uses the default password, which is NotASecret. If you stored the password with a keycode
/// you must use that keycode to decrypt and if you used the default value to encrypt you must use the default
/// password to decrypt.
/// </summary>
/// <param name="userTypedPassword">The password typed in by a user for a login attempt.</param>
/// <param name="storedPasswordHash">The password hash that is stored with the salt.</param>
/// <returns></returns>
public static bool VerifyHash(string userTypedPassword, string storedPasswordHash)
{
return VerifyHash(userTypedPassword, DefaultPassword, storedPasswordHash);
}
#endregion
#region VerifyHash(string userTypedPassword, string keyCode, string storedPasswordHash)
/// <summary>
/// This method is used to verify the Hash created is the same as a hash stored in the database.
/// </summary>
/// <param name="password"></param>
/// <param name="keyCode"></param>
/// <param name="salt"></param>
/// <returns></returns>
public static bool VerifyHash(string userTypedPassword, string keyCode, string storedPasswordHash)
{
// initial value
bool verified = false;
try
{
// locals
// get the password up until the separator
string password = "";
string salty = "";
byte[] salt = null;
byte[] storedHash = null;
// if all the parameters exist
if (TextHelper.Exists(userTypedPassword, keyCode, storedPasswordHash))
{
// we must first decrypt the storedPasswordHash with the keycode
string decryptedHash = DecryptString(storedPasswordHash, keyCode);
// if the decryptedHash exists
if (TextHelper.Exists(decryptedHash))
{
// get the index of the 4 pipe characters
int index = decryptedHash.IndexOf("||||");
// if the index was found
if (index >= 0)
{
// get the password
password = decryptedHash.Substring(0, index);
salty = decryptedHash.Substring(index + 4);
salt = Encoding.Unicode.GetBytes(salty);
storedHash = Encoding.Unicode.GetBytes(password);
}
// now verify with the override
verified = VerifyHash(userTypedPassword, salt, storedHash);
}
}
}
catch
{
}
// return value
return verified;
}
#endregion
#region VerifyHash(string password, byte[] salt, byte[] storedHash)
/// <summary>
/// This method is used to verify the Hash created is the same as the
/// </summary>
/// <param name="password"></param>
/// <param name="keyCode"></param>
/// <param name="salt"></param>
/// <param name="newHash"></param>
/// <returns></returns>
public static bool VerifyHash(string password, byte[] salt, byte[] storedHash)
{
// initial value
bool verified = false;
// if all the parameters exist
if (TextHelper.Exists(password) && (salt.Length > 0) && (storedHash.Length > 0))
{
// generate the loginHash again
var newHash = HashPassword(password, salt);
// set the return value
verified = storedHash.SequenceEqual(newHash);
}
// return value
return verified;
}
#endregion
#endregion
}
#endregion
}
以及使用上述项目的示例项目:https://github.com/DataJuggler/Blazor.Crypto
并且现场演示在我的网站上:https://blazorcrypto.datajuggler.com/
视频教程在这里:https://youtu.be/w4NrmpeHykE
并且对于不想帮助那位可能会阅读此帖子或代码的1个人有用的Stack Overflow主持人,为什么不希望他们学习?
[如果我冒犯了任何人,对不起。如果1个人学到了一些东西或发现任何免费的有用代码,则它不是垃圾邮件。互联网上没有一个地方免费为免费提供代码的开发人员与其他可能需要它的开发人员进行交流。
谢谢