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 message digests. 98 * 99 * @returns {Array} The available message digests. 100 */ 101 availableMessageDigests : function() { 102 return Object.values(jls.security.MessageDigest._availableMessageDigests); 103 }, 104 addMessageDigest : function(md) { 105 if ((typeof md == 'undefined') || (md == null) || (! (md instanceof jls.security.MessageDigest))) { 106 throw new jls.lang.Exception('Invalid message digest parameter'); 107 } 108 jls.security.MessageDigest._availableMessageDigests[md.getAlgorithm()] = md; 109 }, 110 /** 111 * Tells if the specified algorithm is supported. 112 * 113 * @param {String} algorithm The algorithm name. 114 * @returns {Boolean} true if the specified algorithm is supported. 115 */ 116 isSupported : function(algorithm) { 117 if (typeof algorithm != 'string') { 118 throw new jls.lang.Exception('Invalid algorithm name'); 119 } 120 if (algorithm in jls.security.MessageDigest._availableMessageDigests) { 121 return true; 122 } 123 if (algorithm in jls.security.MessageDigest._algorithmMapping) { 124 jls.loader.require(jls.security.MessageDigest._algorithmMapping[algorithm]); 125 return algorithm in jls.security.MessageDigest._availableMessageDigests; 126 } 127 return false; 128 }, 129 /** 130 * Returns the specified message digest. 131 * 132 * @param {String} algorithm The message digest algorithm name. 133 * @returns {jls.security.MessageDigest} The message digest. 134 */ 135 getInstance : function(algorithm) { 136 if (! jls.security.MessageDigest.isSupported(algorithm)) { 137 throw new jls.lang.Exception('Unsupported algorithm "' + algorithm + '"'); 138 } 139 return jls.security.MessageDigest._availableMessageDigests[algorithm]; 140 } 141 }); 142