1 jls.loader.provide('jls.security.MessageDigest'); 2 3 jls.loader.require('jls.lang.ByteBuffer'); 4 jls.loader.require('jls.io.BufferChannel'); 5 6 /** 7 * @namespace Provides security classes for the jls language. 8 * @see jls.security.MessageDigest 9 * @name jls.security 10 */ 11 12 /** 13 * @class This class represents a cryptographic hash function. 14 * The message digests are MD5(not implemented) and SHA1. 15 */ 16 jls.security.MessageDigest = jls.lang.Class.create( /** @lends jls.security.MessageDigest.prototype */ 17 { 18 /** 19 * Creates a MessageDigest. 20 * 21 * @private 22 */ 23 initialize : function(algorithm) { 24 this._algorithm = algorithm; 25 this._buffer = jls.lang.ByteBuffer.allocate(1024); 26 }, 27 /** 28 * Returns the algorithm name. 29 * 30 * @returns {String} The algorithm name. 31 */ 32 getAlgorithm : function() { 33 return this._algorithm; 34 }, 35 /** 36 * Completes the digest and returns a buffer. 37 * 38 * @returns {jls.lang.ByteBuffer} The digested buffer. 39 */ 40 digest : function() { 41 throw new jls.lang.Exception('Not implemented'); 42 }, 43 /** 44 * Resets the digest. 45 * 46 */ 47 reset : function() { 48 this._buffer.clear(); 49 }, 50 _checkRemaining : function(length) { 51 if (this._buffer.remaining() >= length) { 52 return; 53 } 54 var capacity = this._buffer.capacity() * 2; 55 for (; length > capacity - this._buffer.capacity(); capacity = capacity * 2); 56 var tmp = jls.lang.ByteBuffer.allocate(capacity); 57 this._buffer.flip(); 58 tmp.putBuffer(this._buffer); 59 this._buffer = tmp; 60 }, 61 /** 62 * Updates the digest with a specified buffer. 63 * 64 * @param {jls.lang.ByteBuffer} buffer The buffer to update. 65 */ 66 update : function(buffer) { 67 this._checkRemaining(buffer.remaining()); 68 this._buffer.putBuffer(buffer, buffer.remaining()); 69 }, 70 /** 71 * Updates the digest with a specified byte. 72 * 73 * @param {Number} b The byte to update. 74 */ 75 updateByte : function(b) { 76 this._checkRemaining(1); 77 this._buffer.putByte(b); 78 }, 79 /** 80 * Updates the digest with a specified string. 81 * 82 * @param {String} buffer The string to update. 83 */ 84 updateString : function(s, csn) { 85 this._checkRemaining(s.length * 2); 86 this._buffer.putString(s, csn ? csn : 'UTF-8'); 87 } 88 }); 89 90 Object.extend(jls.security.MessageDigest, /** @lends jls.security.MessageDigest */ 91 { 92 _algorithmMapping : { 93 'SHA1' : 'jls.security.Sha1' 94 }, 95 _availableMessageDigests : {}, 96 /** 97 * Returns available algorithms. 98 * 99 * @returns {Array} The available algorithms. 100 */ 101 availableAlgorithms : function() { 102 return Object.keys(jls.security.MessageDigest._availableMessageDigests); 103 }, 104 addMessageDigest : function(mdc) { 105 if ((typeof mdc == 'undefined') || (mdc == null)) { 106 throw new jls.lang.Exception('Invalid message digest argument'); 107 } 108 var md = new mdc(); 109 if (! (md instanceof jls.security.MessageDigest)) { 110 throw new jls.lang.Exception('Invalid message digest argument (not an instance of MessageDigest)'); 111 } 112 jls.security.MessageDigest._availableMessageDigests[md.getAlgorithm()] = mdc; 113 }, 114 /** 115 * Tells if the specified algorithm is supported. 116 * 117 * @param {String} algorithm The algorithm name. 118 * @returns {Boolean} true if the specified algorithm is supported. 119 */ 120 isSupported : function(algorithm) { 121 if (typeof algorithm != 'string') { 122 throw new jls.lang.Exception('Invalid algorithm name'); 123 } 124 if (algorithm in jls.security.MessageDigest._availableMessageDigests) { 125 return true; 126 } 127 if (algorithm in jls.security.MessageDigest._algorithmMapping) { 128 jls.loader.require(jls.security.MessageDigest._algorithmMapping[algorithm]); 129 return algorithm in jls.security.MessageDigest._availableMessageDigests; 130 } 131 return false; 132 }, 133 /** 134 * Returns the specified message digest. 135 * 136 * @param {String} algorithm The message digest algorithm name. 137 * @returns {jls.security.MessageDigest} The message digest. 138 */ 139 getInstance : function(algorithm) { 140 if (! jls.security.MessageDigest.isSupported(algorithm)) { 141 throw new jls.lang.Exception('Unsupported algorithm "' + algorithm + '"'); 142 } 143 return new jls.security.MessageDigest._availableMessageDigests[algorithm](); 144 } 145 }); 146