166 lines
5.2 KiB
C#
166 lines
5.2 KiB
C#
/*
|
|
Copyright 2001-2007 Markus Hahn
|
|
All rights reserved. See documentation for license details.
|
|
*/
|
|
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace DG.Tool
|
|
{
|
|
|
|
/// <summary>An easy-to-use-string encryption solution using Blowfish/CBC.</summary>
|
|
/// <remarks>As a simple solution for developers, who want nothing more than protect
|
|
/// single strings with a password, this class provides the necessary functionality.
|
|
/// The password (aka as key) is hashed using the SHA-1 implementation of the .NET
|
|
/// framework. The random number generator for the CBC initialization vector (IV)
|
|
/// and BASE64 are used from the framework's security services.</remarks>
|
|
public class BlowfishSimple
|
|
{
|
|
BlowfishCBC bfc;
|
|
|
|
private byte[] iv;
|
|
|
|
private byte[] IV
|
|
{
|
|
get
|
|
{
|
|
if (iv == null || iv.Length < 8)
|
|
{
|
|
return Encoding.UTF8.GetBytes("Blowfish");
|
|
}
|
|
return iv;
|
|
}
|
|
set { iv = value; }
|
|
}
|
|
|
|
static byte[] TransformKey(String key)
|
|
{
|
|
UTF8Encoding ue = new UTF8Encoding();
|
|
return ue.GetBytes(key);
|
|
}
|
|
|
|
/// <summary>Empty constructor. Before using the instance you MUST call Initialize(),
|
|
/// otherwise any result or behavior is unpredictable!</summary>
|
|
public BlowfishSimple()
|
|
{
|
|
}
|
|
|
|
/// <summary>Default constructor.</summary>
|
|
/// <param name="keyStr">The string which is used as the key material (aka as
|
|
/// password or passphrase). Internally the UTF-8 representation of this string
|
|
/// is used, hashed with SHA-1. The result is then a 160bit binary key. Notice
|
|
/// that this transformation will not make weak (meaning short or easily guessable)
|
|
/// keys any safer!</param>
|
|
public BlowfishSimple(String keyStr)
|
|
{
|
|
Initialize(keyStr, null);
|
|
}
|
|
|
|
public BlowfishSimple(String keyStr, Byte[] iv)
|
|
{
|
|
Initialize(keyStr, iv);
|
|
}
|
|
|
|
/// <summary>Initializes the instance with a (new) key string.</summary>
|
|
/// <param name="keyStr">The key material.</param>
|
|
/// <see cref="BlowfishSimple(String)"/>
|
|
public void Initialize(String keyStr, Byte[] iv)
|
|
{
|
|
IV = iv;
|
|
byte[] key = TransformKey(keyStr);
|
|
|
|
this.bfc = new BlowfishCBC(key, 0, key.Length);
|
|
Array.Clear(key, 0, key.Length);
|
|
}
|
|
|
|
|
|
|
|
/// <summary>Encrypts a string.</summary>
|
|
/// <remarks>For efficiency the given string will be UTF-8 encoded and padded to
|
|
/// the next 8byte block border. The CBC IV plus the encrypted data will then be
|
|
/// BASE64 encoded and returned as the final encryption result.</remarks>
|
|
/// <param name="plainText">The string to encrypt.</param>
|
|
/// <returns>The encrypted string.</returns>
|
|
public String Encrypt(String plainText)
|
|
{
|
|
return Encrypt(plainText, this.IV);
|
|
}
|
|
|
|
public String Encrypt(String plainText, byte[] iv)
|
|
{
|
|
if (string.IsNullOrEmpty(plainText)) return string.Empty;
|
|
int txtLen = plainText.Length;
|
|
if (txtLen % 8 != 0)
|
|
plainText = plainText.PadRight(txtLen - txtLen % 8 + 8, ' ');
|
|
byte[] ueData = Encoding.UTF8.GetBytes(plainText);
|
|
|
|
int origLen = ueData.Length;
|
|
|
|
byte[] inBuf = new byte[origLen];
|
|
|
|
Array.Copy(ueData, 0, inBuf, 0, origLen);
|
|
|
|
byte[] outBuf = new byte[inBuf.Length];
|
|
|
|
this.bfc.IV = iv;
|
|
|
|
this.bfc.Encrypt(
|
|
inBuf,
|
|
0,
|
|
outBuf,
|
|
0,
|
|
inBuf.Length);
|
|
|
|
String sResult = Convert.ToBase64String(outBuf);
|
|
|
|
Array.Clear(inBuf, 0, inBuf.Length);
|
|
|
|
return sResult;
|
|
}
|
|
|
|
/// <summary>Decrypts a string which was formely generated by the Encrypt()
|
|
/// method and a particular key.</summary>
|
|
/// <remarks>The string has to be decrypted with the same key, otherwise the
|
|
/// result will be simply garbage. If you want to check if the key is the right
|
|
/// one use the VerifyKey() method.</remarks>
|
|
/// <param name="cipherText">The string to decrypt.</param>
|
|
/// <returns>The decrypted string, or null on error (usually caused by a wrong
|
|
/// key passed in).</returns>
|
|
|
|
public String Decrypt(String cipherText)
|
|
{
|
|
return Decrypt(cipherText, this.IV);
|
|
}
|
|
|
|
public String Decrypt(String cipherText, byte[] iv)
|
|
{
|
|
byte[] cdata;
|
|
|
|
try
|
|
{
|
|
cdata = Convert.FromBase64String(cipherText);
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
this.bfc.SetIV(iv, 0);
|
|
|
|
byte[] outBuf = new byte[cdata.Length];
|
|
|
|
int dataAbs = outBuf.Length;
|
|
|
|
this.bfc.Decrypt(
|
|
cdata,
|
|
0,
|
|
outBuf,
|
|
0,
|
|
dataAbs);
|
|
|
|
return Encoding.UTF8.GetString(outBuf);
|
|
}
|
|
}
|
|
}
|