diff --git a/Confuser.Renamer/ReversibleRenamer.cs b/Confuser.Renamer/ReversibleRenamer.cs index c5cdf154..9d6b9b7c 100644 --- a/Confuser.Renamer/ReversibleRenamer.cs +++ b/Confuser.Renamer/ReversibleRenamer.cs @@ -5,8 +5,8 @@ namespace Confuser.Renamer { public class ReversibleRenamer { - RijndaelManaged cipher; - byte[] key; + readonly RijndaelManaged cipher; + readonly byte[] key; public ReversibleRenamer(string password) { cipher = new RijndaelManaged(); @@ -14,13 +14,32 @@ public ReversibleRenamer(string password) { cipher.Key = key = sha.ComputeHash(Encoding.UTF8.GetBytes(password)); } - static string Base64Encode(byte[] buf) { - return Convert.ToBase64String(buf).Trim('=').Replace('+', '$').Replace('/', '_'); + public string Encrypt(string name) { + byte ivId = GetIVId(name); + cipher.IV = GetIV(ivId); + var buf = Encoding.UTF8.GetBytes(name); + + using (var ms = new MemoryStream()) { + ms.WriteByte(ivId); + using (var stream = new CryptoStream(ms, cipher.CreateEncryptor(), CryptoStreamMode.Write)) { + stream.Write(buf, 0, buf.Length); + stream.FlushFinalBlock(); + return Base64Encode(ms.GetBuffer(), (int)ms.Length); + } + } } - static byte[] Base64Decode(string str) { - str = str.Replace('$', '+').Replace('_', '/').PadRight((str.Length + 3) & ~3, '='); - return Convert.FromBase64String(str); + public string Decrypt(string name) { + using (var ms = new MemoryStream(Base64Decode(name))) { + byte ivId = (byte)ms.ReadByte(); + cipher.IV = GetIV(ivId); + + using (var result = new MemoryStream()) { + using (var stream = new CryptoStream(ms, cipher.CreateDecryptor(), CryptoStreamMode.Read)) + stream.CopyTo(result); + return Encoding.UTF8.GetString(result.GetBuffer(), 0, (int)result.Length); + } + } } byte[] GetIV(byte ivId) { @@ -37,32 +56,48 @@ byte GetIVId(string str) { return x; } - public string Encrypt(string name) { - byte ivId = GetIVId(name); - cipher.IV = GetIV(ivId); - var buf = Encoding.UTF8.GetBytes(name); + static string Base64Encode(byte[] buffer, int length) { + int inputUnpaddedLength = 4 * length / 3; + var outArray = new char[(inputUnpaddedLength + 3) & ~3]; + Convert.ToBase64CharArray(buffer, 0, length, outArray, 0); - using (var ms = new MemoryStream()) { - ms.WriteByte(ivId); - using (var stream = new CryptoStream(ms, cipher.CreateEncryptor(), CryptoStreamMode.Write)) - stream.Write(buf, 0, buf.Length); + var result = new StringBuilder(inputUnpaddedLength); + foreach (var oldChar in outArray) { + if (oldChar == '=') { + break; + } - buf = ms.ToArray(); - return Base64Encode(buf); + result.Append(oldChar == '+' + ? '$' + : oldChar == '/' + ? '_' + : oldChar); } - } - public string Decrypt(string name) { - using (var ms = new MemoryStream(Base64Decode(name))) { - byte ivId = (byte)ms.ReadByte(); - cipher.IV = GetIV(ivId); + return result.ToString(); + } - var result = new MemoryStream(); - using (var stream = new CryptoStream(ms, cipher.CreateDecryptor(), CryptoStreamMode.Read)) - stream.CopyTo(result); + static byte[] Base64Decode(string str) { + var newLength = (str.Length + 3) & ~3; + var inArray = new char[newLength]; + for (int index = 0; index < newLength; index++) { + char newChar; + if (index < str.Length) { + char oldChar = str[index]; + newChar = oldChar == '$' + ? '+' + : oldChar == '_' + ? '/' + : oldChar; + } + else { + newChar = '='; + } - return Encoding.UTF8.GetString(result.ToArray()); + inArray[index] = newChar; } + + return Convert.FromBase64CharArray(inArray, 0, inArray.Length); } } -} \ No newline at end of file +}