Mes documents/Visual Studio 2005/Projects/TES4ModTranslator/TES4ModTranslator/Encryption/PkzipClassic.cs

Go to the documentation of this file.
00001 //
00002 // PkzipClassic encryption
00003 //
00004 // Copyright 2004 John Reilly
00005 //
00006 // This program is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU General Public License
00008 // as published by the Free Software Foundation; either version 2
00009 // of the License, or (at your option) any later version.
00010 //
00011 // This program is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU General Public License
00017 // along with this program; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 //
00020 // Linking this library statically or dynamically with other modules is
00021 // making a combined work based on this library.  Thus, the terms and
00022 // conditions of the GNU General Public License cover the whole
00023 // combination.
00024 // 
00025 // As a special exception, the copyright holders of this library give you
00026 // permission to link this library with independent modules to produce an
00027 // executable, regardless of the license terms of these independent
00028 // modules, and to copy and distribute the resulting executable under
00029 // terms of your choice, provided that you also meet, for each linked
00030 // independent module, the terms and conditions of the license of that
00031 // module.  An independent module is a module which is not derived from
00032 // or based on this library.  If you modify this library, you may extend
00033 // this exception to your version of the library, but you are not
00034 // obligated to do so.  If you do not wish to do so, delete this
00035 // exception statement from your version.
00036 //
00037 
00038 using System;
00039 using System.Security.Cryptography;
00040 
00041 using ICSharpCode.SharpZipLib.Checksums;
00042 
00043 namespace ICSharpCode.SharpZipLib.Encryption
00044 {
00050         public abstract class PkzipClassic  : SymmetricAlgorithm
00051         {
00055                 static public byte[] GenerateKeys(byte[] seed)
00056                 {
00057                         if ( seed == null ) 
00058                         {
00059                                 throw new ArgumentNullException("seed");
00060                         }
00061 
00062                         if ( seed.Length == 0 )
00063                         {
00064                                 throw new ArgumentException("seed");
00065                         }
00066 
00067                         uint[] newKeys = new uint[] {
00068                                                     0x12345678,
00069                                                     0x23456789,
00070                                                     0x34567890
00071                                                  };
00072                         
00073                         for (int i = 0; i < seed.Length; ++i) 
00074                         {
00075                                 newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]);
00076                                 newKeys[1] = newKeys[1] + (byte)newKeys[0];
00077                                 newKeys[1] = newKeys[1] * 134775813 + 1;
00078                                 newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24));
00079                         }
00080 
00081                         byte[] result = new byte[12];
00082                         result[0] = (byte)(newKeys[0] & 0xff);
00083                         result[1] = (byte)((newKeys[0] >> 8) & 0xff);
00084                         result[2] = (byte)((newKeys[0] >> 16) & 0xff);
00085                         result[3] = (byte)((newKeys[0] >> 24) & 0xff);
00086                         result[4] = (byte)(newKeys[1] & 0xff);
00087                         result[5] = (byte)((newKeys[1] >> 8) & 0xff);
00088                         result[6] = (byte)((newKeys[1] >> 16) & 0xff);
00089                         result[7] = (byte)((newKeys[1] >> 24) & 0xff);
00090                         result[8] = (byte)(newKeys[2] & 0xff);
00091                         result[9] = (byte)((newKeys[2] >> 8) & 0xff);
00092                         result[10] = (byte)((newKeys[2] >> 16) & 0xff);
00093                         result[11] = (byte)((newKeys[2] >> 24) & 0xff);
00094                         return result;
00095                 }
00096         }
00097 
00102         class PkzipClassicCryptoBase
00103         {
00104                 uint[] keys     = null;
00105 
00112                 protected byte TransformByte()
00113                 {
00114                         uint temp = ((keys[2] & 0xFFFF) | 2);
00115                         return (byte)((temp * (temp ^ 1)) >> 8);
00116                 }
00117 
00118                 protected void SetKeys(byte[] keyData)
00119                 {
00120                         if ( keyData == null ) {
00121                                 throw new ArgumentNullException("keyData");
00122                         }
00123                 
00124                         if ( keyData.Length != 12 ) {
00125                                 throw new InvalidOperationException("Keys not valid");
00126                         }
00127                         
00128                         keys = new uint[3];
00129                         keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]);
00130                         keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]);
00131                         keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]);
00132                 }
00133 
00137                 protected void UpdateKeys(byte ch)
00138                 {
00139                         keys[0] = Crc32.ComputeCrc32(keys[0], ch);
00140                         keys[1] = keys[1] + (byte)keys[0];
00141                         keys[1] = keys[1] * 134775813 + 1;
00142                         keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
00143                 }
00144 
00148                 protected void Reset()
00149                 {
00150                         keys[0] = 0;
00151                         keys[1] = 0;
00152                         keys[2] = 0;
00153                 }
00154         }
00155 
00159         class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform
00160         {
00165                 internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock)
00166                 {
00167                         SetKeys(keyBlock);
00168                 }
00169 
00170                 #region ICryptoTransform Members
00171 
00179                 public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
00180                 {
00181                         byte[] result = new byte[inputCount];
00182                         TransformBlock(inputBuffer, inputOffset, inputCount, result, 0);
00183                         return result;
00184                 }
00185 
00196                 public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
00197                 {
00198                         for (int i = inputOffset; i < inputOffset + inputCount; ++i) {
00199                                 byte oldbyte = inputBuffer[i];
00200                                 outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte());
00201                                 UpdateKeys(oldbyte);
00202                         }
00203                         return inputCount;
00204                 }
00205 
00209                 public bool CanReuseTransform
00210                 {
00211                         get {
00212                                 return true;
00213                         }
00214                 }
00215 
00219                 public int InputBlockSize
00220                 {
00221                         get {
00222                                 return 1;
00223                         }
00224                 }
00225 
00229                 public int OutputBlockSize
00230                 {
00231                         get {
00232                                 return 1;
00233                         }
00234                 }
00235 
00239                 public bool CanTransformMultipleBlocks
00240                 {
00241                         get {
00242                                 return true;
00243                         }
00244                 }
00245 
00246                 #endregion
00247 
00248                 #region IDisposable Members
00249 
00253                 public void Dispose()
00254                 {
00255                         Reset();
00256                 }
00257 
00258                 #endregion
00259         }
00260 
00261 
00265         class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform
00266         {
00271                 internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock)
00272                 {
00273                         SetKeys(keyBlock);
00274                 }
00275 
00276                 #region ICryptoTransform Members
00277 
00285                 public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
00286                 {
00287                         byte[] result = new byte[inputCount];
00288                         TransformBlock(inputBuffer, inputOffset, inputCount, result, 0);
00289                         return result;
00290                 }
00291 
00302                 public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
00303                 {
00304                         for (int i = inputOffset; i < inputOffset + inputCount; ++i) {
00305                                 byte newByte = (byte)(inputBuffer[i] ^ TransformByte());
00306                                 outputBuffer[outputOffset++] = newByte;
00307                                 UpdateKeys(newByte);
00308                         }
00309                         return inputCount;
00310                 }
00311 
00315                 public bool CanReuseTransform
00316                 {
00317                         get {
00318                                 return true;
00319                         }
00320                 }
00321 
00325                 public int InputBlockSize
00326                 {
00327                         get {
00328                                 return 1;
00329                         }
00330                 }
00331 
00335                 public int OutputBlockSize
00336                 {
00337                         get {
00338                                 return 1;
00339                         }
00340                 }
00341 
00345                 public bool CanTransformMultipleBlocks
00346                 {
00347                         get {
00348                                 return true;
00349                         }
00350                 }
00351 
00352                 #endregion
00353 
00354                 #region IDisposable Members
00355 
00359                 public void Dispose()
00360                 {
00361                         Reset();
00362                 }
00363 
00364                 #endregion
00365         }
00366 
00371         public sealed class PkzipClassicManaged : PkzipClassic
00372         {
00377                 public override int BlockSize 
00378                 {
00379                         get { return 8; }
00380                         set {
00381                                 if (value != 8)
00382                                         throw new CryptographicException();
00383                         }
00384                 }
00385 
00389                 public override KeySizes[] LegalKeySizes
00390                 {
00391                         get {
00392                                 KeySizes[] keySizes = new KeySizes[1];
00393                                 keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0);
00394                                 return keySizes; 
00395                         }
00396                 }
00397 
00401                 public override void GenerateIV()
00402                 {
00403                         // Do nothing.
00404                 }
00405 
00409                 public override KeySizes[] LegalBlockSizes
00410                 {
00411                         get {
00412                                 KeySizes[] keySizes = new KeySizes[1];
00413                                 keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0);
00414                                 return keySizes; 
00415                         }
00416                 }
00417 
00418                 byte[] key;
00419 
00423                 public override byte[] Key
00424                 {
00425                         get {
00426                                 return key;
00427                         }
00428                 
00429                         set {
00430                                 key = value;
00431                         }
00432                 }
00433 
00437                 public override void GenerateKey()
00438                 {
00439                         key = new byte[12];
00440                         Random rnd = new Random();
00441                         rnd.NextBytes(key);
00442                 }
00443 
00450                 public override ICryptoTransform CreateEncryptor(
00451                         byte[] rgbKey,
00452                         byte[] rgbIV
00453                 )
00454                 {
00455                         return new PkzipClassicEncryptCryptoTransform(rgbKey);
00456                 }
00457 
00464                 public override ICryptoTransform CreateDecryptor(
00465                         byte[] rgbKey,
00466                         byte[] rgbIV
00467                 )
00468                 {
00469                         return new PkzipClassicDecryptCryptoTransform(rgbKey);
00470                 }
00471         }
00472 }

Generated on Fri Jun 23 21:50:04 2006 for OblivionModTranslator by  doxygen 1.4.6-NO