Signing and verifying with byte arrays
diff --git a/js/securityLib/rsa.js b/js/securityLib/rsa.js
index 66baa27..11efe45 100644
--- a/js/securityLib/rsa.js
+++ b/js/securityLib/rsa.js
@@ -24,7 +24,11 @@
return b.toString(16);
}
-// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
+/**
+ * PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
+ * @param s: the string to encode
+ * @param n: the size in byte
+ */
function pkcs1pad2(s,n) {
if(n < s.length + 11) { // TODO: fix for utf-8
alert("Message too long for RSA");
diff --git a/js/securityLib/rsa2.js b/js/securityLib/rsa2.js
index e1f3f27..d75814e 100644
--- a/js/securityLib/rsa2.js
+++ b/js/securityLib/rsa2.js
@@ -57,7 +57,9 @@
alert("Invalid RSA private key");
}
-// Generate a new random private key B bits long, using public expt E
+/**
+ * Generate a new random private key B bits long, using public expt E
+ */
function RSAGenerate(B,E) {
var rng = new SecureRandom();
var qs = B>>1;
@@ -91,7 +93,10 @@
}
}
-// Perform raw private operation on "x": return x^d (mod n)
+/**
+ * Perform raw private operation on "x": return x^d (mod n)
+ * @return x^d (mod n)
+ */
function RSADoPrivate(x) {
if(this.p == null || this.q == null)
return x.modPow(this.d, this.n);
diff --git a/js/securityLib/rsasign-1.2.js b/js/securityLib/rsasign-1.2.js
index 645bf28..66cef59 100644
--- a/js/securityLib/rsasign-1.2.js
+++ b/js/securityLib/rsasign-1.2.js
@@ -56,6 +56,10 @@
_RSASIGN_HASHHEXFUNC['md5'] = function(s){return hex_md5(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return hex_rmd160(s);}; // http://pajhome.org.uk/crypt/md5/md5.html
+//@author axelcdv
+var _RSASIGN_HASHBYTEFUNC = [];
+_RSASIGN_HASHBYTEFUNC['sha256'] = function(byteArray){return hex_sha256_from_bytes(byteArray);};
+
//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
@@ -100,6 +104,29 @@
return sPaddedMessageHex;
}
+/**
+ * Apply padding, then computes the hash of the given byte array, according to the key size and with the hash algorithm
+ * @param byteArray (byte[])
+ * @param keySize (int)
+ * @param hashAlg the hash algorithm to apply (string)
+ * @return the hash of byteArray
+ */
+function _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, keySize, hashAlg){
+ var pmStrLen = keySize / 4;
+ var hashFunc = _RSASIGN_HASHBYTEFUNC[hashAlg];
+ var sHashHex = hashFunc(byteArray); //returns hex hash
+
+ var sHead = "0001";
+ var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
+ var sMid = "";
+ var fLen = pmStrLen - sHead.length - sTail.length;
+ for (var i = 0; i < fLen; i += 2) {
+ sMid += "ff";
+ }
+ sPaddedMessageHex = sHead + sMid + sTail;
+ return sPaddedMessageHex;
+}
+
function _zeroPaddingOfSignature(hex, bitLength) {
var s = "";
var nZero = bitLength / 4 - hex.length;
@@ -138,6 +165,34 @@
}
+/**
+ * Sign a message byteArray with an RSA private key
+ * @name signByteArray
+ * @memberOf RSAKey#
+ * @function
+ * @param {byte[]} byteArray
+ * @param {Sring} hashAlg the hash algorithm to apply
+ * @param {RSAKey} rsa key to sign with: hack because the context is lost here
+ * @return hexadecimal string of signature value
+ */
+function _rsasign_signByteArray(byteArray, hashAlg, rsaKey) {
+ var hPM = _rsasign_getHexPaddedDigestInfoForByteArray(byteArray, rsaKey.n.bitLength(), hashAlg); ///hack because the context is lost here
+ var biPaddedMessage = parseBigInt(hPM, 16);
+ var biSign = rsaKey.doPrivate(biPaddedMessage); //hack because the context is lost here
+ var hexSign = biSign.toString(16);
+ return _zeroPaddingOfSignature(hexSign, rsaKey.n.bitLength()); //hack because the context is lost here
+}
+
+/**
+ * Sign a byte array with the Sha-256 algorithm
+ * @param {byte[]} byteArray
+ * @return hexadecimal string of signature value
+ */
+function _rsasign_signByteArrayWithSHA256(byteArray){
+ return _rsasign_signByteArray(byteArray, 'sha256', this); //Hack because the context is lost in the next function
+}
+
+
function _rsasign_signStringWithSHA1(s) {
return _rsasign_signString(s, 'sha1');
}
@@ -225,8 +280,42 @@
return (diHashValue == msgHashValue);
}
+/**
+ * verifies a sigature for a message byte array with RSA public key.<br/>
+ * @name verifyByteArray
+ * @memberOf RSAKey#
+ * @function
+ * @param {byte[]} byteArray message byte array to be verified.
+ * @param {String} hSig hexadecimal string of signature.<br/>
+ * non-hexadecimal charactors including new lines will be ignored.
+ * @return returns 1 if valid, otherwise 0
+ */
+function _rsasign_verifyByteArray(byteArray, hSig) {
+ hSig = hSig.replace(_RE_HEXDECONLY, '');
+
+ if(LOG>3)console.log('n is '+this.n);
+ if(LOG>3)console.log('e is '+this.e);
+
+ if (hSig.length != this.n.bitLength() / 4) return 0;
+ hSig = hSig.replace(/[ \n]+/g, "");
+ var biSig = parseBigInt(hSig, 16);
+ var biDecryptedSig = this.doPublic(biSig);
+ var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
+ var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
+
+ if (digestInfoAry.length == 0) return false;
+ var algName = digestInfoAry[0];
+ var diHashValue = digestInfoAry[1];
+ var ff = _RSASIGN_HASHBYTEFUNC[algName];
+ var msgHashValue = ff(byteArray);
+ return (diHashValue == msgHashValue);
+}
+
RSAKey.prototype.signString = _rsasign_signString;
+RSAKey.prototype.signByteArray = _rsasign_signByteArray; //@author axelcdv
+RSAKey.prototype.signByteArrayWithSHA256 = _rsasign_signByteArrayWithSHA256; //@author axelcdv
+
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.sign = _rsasign_signString;
@@ -242,7 +331,7 @@
RSAKey.prototype.signWithSHA256HEX = _rsasign_signStringWithSHA256HEX;
*/
-
+RSAKey.prototype.verifyByteArray = _rsasign_verifyByteArray;
RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verify = _rsasign_verifyString;
diff --git a/js/securityLib/sha256.js b/js/securityLib/sha256.js
index b3b38da..45f3cb3 100644
--- a/js/securityLib/sha256.js
+++ b/js/securityLib/sha256.js
@@ -20,6 +20,15 @@
* They take string arguments and return either hex or base-64 encoded strings
*/
+//@author axelcdv
+/**
+ * Computes the Sha-256 hash of the given byte array
+ * @param {byte[]}
+ * @return the hex string corresponding to the Sha-256 hash of the byte array
+ */
+function hex_sha256_from_bytes(byteArray){
+ return rstr2hex(binb2rstr(binb_sha256( byteArray2binb(byteArray), byteArray.length * 8)));
+}
function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
@@ -53,15 +62,16 @@
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
}
-/*
+/**
* Calculate the sha256 of a raw string
+ * @param s: the raw string
*/
function rstr_sha256(s)
{
return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
}
-/*
+/**
* Calculate the HMAC-sha256 of a key and some data (raw strings)
*/
function rstr_hmac_sha256(key, data)
@@ -80,7 +90,7 @@
return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
}
-/*
+/**
* Convert a raw string to a hex string
*/
function rstr2hex(input)
@@ -234,7 +244,7 @@
return output;
}
-/*
+/**
* Convert a raw string to an array of big-endian words
* Characters >255 have their high-byte silently ignored.
*/
@@ -249,6 +259,22 @@
return output;
}
+/**
+ * @author axelcdv
+ * Convert a byte array to an array of big-endian words
+ * @param {byte[]} input
+ * @return the array of big-endian words
+ */
+function byteArray2binb(input){
+ console.log("Byte array coming is " + input);
+ var output = Array(input.length >> 2);
+ for(var i = 0; i < output.length; i++)
+ output[i] = 0;
+ for(var i = 0; i < input.length * 8; i += 8)
+ output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);
+ return output;
+}
+
/*
* Convert an array of big-endian words to a string
*/