tweetcast/client/lib/websocket-js/flash-src/third-party/com/hurlant/crypto/Crypto.as
changeset 306 70c9688a1486
parent 305 436a31d11f1d
equal deleted inserted replaced
305:436a31d11f1d 306:70c9688a1486
       
     1 /**
       
     2  * Crypto
       
     3  * 
       
     4  * An abstraction layer to instanciate our crypto algorithms
       
     5  * Copyright (c) 2007 Henri Torgemane
       
     6  * 
       
     7  * See LICENSE.txt for full license information.
       
     8  */
       
     9 package com.hurlant.crypto
       
    10 {
       
    11 	import com.hurlant.crypto.hash.HMAC;
       
    12 	import com.hurlant.crypto.hash.MAC;
       
    13 	import com.hurlant.crypto.hash.IHash;
       
    14 	import com.hurlant.crypto.hash.MD2;
       
    15 	import com.hurlant.crypto.hash.MD5;
       
    16 	import com.hurlant.crypto.hash.SHA1;
       
    17 	import com.hurlant.crypto.hash.SHA224;
       
    18 	import com.hurlant.crypto.hash.SHA256;
       
    19 	import com.hurlant.crypto.prng.ARC4;
       
    20 	import com.hurlant.crypto.rsa.RSAKey;
       
    21 	import com.hurlant.crypto.symmetric.AESKey;
       
    22 	import com.hurlant.crypto.symmetric.BlowFishKey;
       
    23 	import com.hurlant.crypto.symmetric.CBCMode;
       
    24 	import com.hurlant.crypto.symmetric.CFB8Mode;
       
    25 	import com.hurlant.crypto.symmetric.CFBMode;
       
    26 	import com.hurlant.crypto.symmetric.CTRMode;
       
    27 	import com.hurlant.crypto.symmetric.DESKey;
       
    28 	import com.hurlant.crypto.symmetric.ECBMode;
       
    29 	import com.hurlant.crypto.symmetric.ICipher;
       
    30 	import com.hurlant.crypto.symmetric.IMode;
       
    31 	import com.hurlant.crypto.symmetric.IPad;
       
    32 	import com.hurlant.crypto.symmetric.ISymmetricKey;
       
    33 	import com.hurlant.crypto.symmetric.IVMode;
       
    34 	import com.hurlant.crypto.symmetric.NullPad;
       
    35 	import com.hurlant.crypto.symmetric.OFBMode;
       
    36 	import com.hurlant.crypto.symmetric.PKCS5;
       
    37 	import com.hurlant.crypto.symmetric.SimpleIVMode;
       
    38 	import com.hurlant.crypto.symmetric.TripleDESKey;
       
    39 	import com.hurlant.crypto.symmetric.XTeaKey;
       
    40 	import com.hurlant.util.Base64;
       
    41 	
       
    42 	import flash.utils.ByteArray;
       
    43 	
       
    44 	/**
       
    45 	 * A class to make it easy to use the rest of the framework.
       
    46 	 * As a side-effect, using this class will cause most of the framework
       
    47 	 * to be linked into your application, which is not always what you want.
       
    48 	 * 
       
    49 	 * If you want to optimize your download size, don't use this class.
       
    50 	 * (But feel free to read it to get ideas on how to get the algorithm you want.)
       
    51 	 */
       
    52 	public class Crypto
       
    53 	{
       
    54 		private var b64:Base64; // we don't use it, but we want the swc to include it, so cheap trick.
       
    55 		
       
    56 		public function Crypto(){
       
    57 		}
       
    58 		
       
    59 		/**
       
    60 		 * Things that should work, among others:
       
    61 		 *  "aes"
       
    62 		 *  "aes-128-ecb"
       
    63 		 *  "aes-128-cbc"
       
    64 		 *  "aes-128-cfb"
       
    65 		 *  "aes-128-cfb8"
       
    66 		 *  "aes-128-ofb"
       
    67 		 *  "aes-192-cfb"
       
    68 		 *  "aes-256-ofb"
       
    69 		 *  "blowfish-cbc"
       
    70 		 *  "des-ecb"
       
    71 		 *  "xtea"
       
    72 		 *  "xtea-ecb"
       
    73 		 *  "xtea-cbc"
       
    74 		 *  "xtea-cfb"
       
    75 		 *  "xtea-cfb8"
       
    76 		 *  "xtea-ofb"
       
    77 		 *  "rc4"
       
    78 		 *  "simple-aes-cbc"
       
    79 		 */
       
    80 		public static function getCipher(name:String, key:ByteArray, pad:IPad=null):ICipher {
       
    81 			// split name into an array.
       
    82 			var keys:Array = name.split("-");
       
    83 			switch (keys[0]) {
       
    84 				/**
       
    85 				 * "simple" is a special case. It means:
       
    86 				 * "If using an IV mode, prepend the IV to the ciphertext"
       
    87 				 */
       
    88 				case "simple":
       
    89 					keys.shift();
       
    90 					name = keys.join("-");
       
    91 					var cipher:ICipher = getCipher(name, key, pad);
       
    92 					if (cipher is IVMode) {
       
    93 						return new SimpleIVMode(cipher as IVMode);
       
    94 					} else {
       
    95 						return cipher;
       
    96 					}
       
    97 				/**
       
    98 				 * we support both "aes-128" and "aes128"
       
    99 				 * Technically, you could use "aes192-128", but you'd
       
   100 				 * only be hurting yourself.
       
   101 				 */
       
   102 				case "aes":
       
   103 				case "aes128":
       
   104 				case "aes192":
       
   105 				case "aes256":
       
   106 					keys.shift();
       
   107 					if (key.length*8==keys[0]) {
       
   108 						// support for "aes-128-..." and such.
       
   109 						keys.shift();
       
   110 					}
       
   111 					return getMode(keys[0], new AESKey(key), pad);
       
   112 				break;
       
   113 				case "bf":
       
   114 				case "blowfish":
       
   115 					keys.shift();
       
   116 					return getMode(keys[0], new BlowFishKey(key), pad);
       
   117 				/**
       
   118 				 * des-ede and des-ede3 are both equivalent to des3.
       
   119 				 * the choice between 2tdes and 3tdes is made based
       
   120 				 * on the length of the key provided.
       
   121 				 */
       
   122 				case "des":
       
   123 					keys.shift();
       
   124 					if (keys[0]!="ede" && keys[0]!="ede3") {
       
   125 						return getMode(keys[0], new DESKey(key), pad);
       
   126 					}
       
   127 					if (keys.length==1) {
       
   128 						keys.push("ecb"); // default mode for 2tdes and 3tdes with openssl enc
       
   129 					}
       
   130 					// fall-through to triple des
       
   131 				case "3des":
       
   132 				case "des3":
       
   133 					keys.shift();
       
   134 					return getMode(keys[0], new TripleDESKey(key), pad);
       
   135 				case "xtea":
       
   136 					keys.shift();
       
   137 					return getMode(keys[0], new XTeaKey(key), pad);
       
   138 				break;
       
   139 				/**
       
   140 				 * Technically, you could say "rc4-128" or whatever,
       
   141 				 * but really, the length of the key is what counts here.
       
   142 				 */
       
   143 				case "rc4":
       
   144 					keys.shift();
       
   145 					return new ARC4(key);
       
   146 				break;
       
   147 			}
       
   148 			return null;
       
   149 		}
       
   150 		
       
   151 		/**
       
   152 		 * Returns the size of a key for a given cipher identifier.
       
   153 		 */
       
   154 		public static function getKeySize(name:String):uint {
       
   155 			var keys:Array = name.split("-");
       
   156 			switch (keys[0]) {
       
   157 				case "simple":
       
   158 					keys.shift();
       
   159 					return getKeySize(keys.join("-"));
       
   160 				case "aes128":
       
   161 					return 16;
       
   162 				case "aes192":
       
   163 					return 24;
       
   164 				case "aes256":
       
   165 					return 32;
       
   166 				case "aes":
       
   167 					keys.shift();
       
   168 					return parseInt(keys[0])/8;
       
   169 				case "bf":
       
   170 				case "blowfish":
       
   171 					return 16;
       
   172 				case "des":
       
   173 					keys.shift();
       
   174 					switch (keys[0]) {
       
   175 						case "ede":
       
   176 							return 16;
       
   177 						case "ede3":
       
   178 							return 24;
       
   179 						default:
       
   180 							return 8;
       
   181 					}
       
   182 				case "3des":
       
   183 				case "des3":
       
   184 					return 24;
       
   185 				case "xtea":
       
   186 					return 8;
       
   187 				case "rc4":
       
   188 					if (parseInt(keys[1])>0) {
       
   189 						return parseInt(keys[1])/8;
       
   190 					}
       
   191 					return 16; // why not.
       
   192 			}
       
   193 			return 0; // unknown;
       
   194 		}
       
   195 		
       
   196 		private static function getMode(name:String, alg:ISymmetricKey, padding:IPad=null):IMode {
       
   197 			switch (name) {
       
   198 				case "ecb":
       
   199 					return new ECBMode(alg, padding);
       
   200 				case "cfb":
       
   201 					return new CFBMode(alg, padding);
       
   202 				case "cfb8":
       
   203 					return new CFB8Mode(alg, padding);
       
   204 				case "ofb":
       
   205 					return new OFBMode(alg, padding);
       
   206 				case "ctr":
       
   207 					return new CTRMode(alg, padding);
       
   208 				case "cbc":
       
   209 				default:
       
   210 					return new CBCMode(alg, padding);
       
   211 			}
       
   212 		}
       
   213 		
       
   214 		/**
       
   215 		 * Things that should work:
       
   216 		 * "md5"
       
   217 		 * "sha"
       
   218 		 * "sha1"
       
   219 		 * "sha224"
       
   220 		 * "sha256"
       
   221 		 */
       
   222 		public static function getHash(name:String):IHash {
       
   223 			switch(name) {
       
   224 				case "md2":
       
   225 					return new MD2;
       
   226 				case "md5":
       
   227 					return new MD5;
       
   228 				case "sha": // let's hope you didn't mean sha-0
       
   229 				case "sha1":
       
   230 					return new SHA1;
       
   231 				case "sha224":
       
   232 					return new SHA224;
       
   233 				case "sha256":
       
   234 					return new SHA256;
       
   235 			}
       
   236 			return null;
       
   237 		}
       
   238 		
       
   239 		/**
       
   240 		 * Things that should work:
       
   241 		 * "sha1"
       
   242 		 * "md5-64"
       
   243 		 * "hmac-md5-96"
       
   244 		 * "hmac-sha1-128"
       
   245 		 * "hmac-sha256-192"
       
   246 		 * etc.
       
   247 		 */
       
   248 		public static function getHMAC(name:String):HMAC {
       
   249 			var keys:Array = name.split("-");
       
   250 			if (keys[0]=="hmac") keys.shift();
       
   251 			var bits:uint = 0;
       
   252 			if (keys.length>1) {
       
   253 				bits = parseInt(keys[1]);
       
   254 			}
       
   255 			return new HMAC(getHash(keys[0]), bits);
       
   256 		}
       
   257 		
       
   258 
       
   259 		public static function getMAC(name:String):MAC {
       
   260 			
       
   261 			var keys:Array = name.split("-");
       
   262 			if (keys[0]=="mac") keys.shift();
       
   263 			var bits:uint = 0;
       
   264 			if (keys.length > 1) {
       
   265 				bits = parseInt(keys[1]);
       
   266 			}
       
   267 			return new MAC(getHash(keys[0]), bits);
       
   268 		}
       
   269 				
       
   270 		
       
   271 		public static function getPad(name:String):IPad {
       
   272 			switch(name) {
       
   273 				case "null":
       
   274 					return new NullPad;
       
   275 				case "pkcs5":
       
   276 				default:
       
   277 					return new PKCS5;
       
   278 			}
       
   279 		}
       
   280 		
       
   281 		/** mostly useless.
       
   282 		 */
       
   283 		public static function getRSA(E:String, M:String):RSAKey {
       
   284 			return RSAKey.parsePublicKey(M,E);
       
   285 		}
       
   286 	}
       
   287 }