00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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
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 }