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