Skip to content

Commit

Permalink
First checkin of code and tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Mar 4, 2011
1 parent 1135666 commit 81d4bce
Show file tree
Hide file tree
Showing 19 changed files with 4,394 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@



TWU_RSA_LIBS = lib/twu-rsa/base64.js lib/twu-rsa/jsbn.js lib/twu-rsa/jsbn2.js lib/twu-rsa/rsa.js lib/twu-rsa/rsa2.js
SANZENREITER_HASH_LIBS = lib/sanzenreiter-hash/sha1.js lib/sanzenreiter-hash/sha256.js
KURUSHIMA_JSRSA_LIBS = lib/kurushima-jsrsa/asn1hex.js lib/kurushima-jsrsa/rsa-pem.js lib/kurushima-jsrsa/rsa-sign.js lib/kurushima-jsrsa/x509.js

LIBS = $(TWU_RSA_LIBS) $(SANZENREITER_HASH_LIBS) $(KURUSHIMA_JSRSA_LIBS)

dist:
mkdir -p build
cat $(LIBS) src/jwt-token.js > build/jwt.js
106 changes: 106 additions & 0 deletions lib/kurushima-jsrsa/asn1hex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//
// asn1hex.js - Hexadecimal represented ASN.1 string library
//
//
// version: 1.0 (2010-Jun-03)
//
// Copyright (c) 2010 Kenji Urushima ([email protected])
//
// This software is licensed under the terms of the MIT License.
// http://www.opensource.org/licenses/mit-license.php
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
//
// Depends on:
//

// MEMO:
// f('3082025b02...', 2) ... 82025b ... 3bytes
// f('020100', 2) ... 01 ... 1byte
// f('0203001...', 2) ... 03 ... 1byte
// f('02818003...', 2) ... 8180 ... 2bytes
// f('3080....0000', 2) ... 80 ... -1
//
// Requirements:
// - ASN.1 type octet length MUST be 1.
// (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
// -
function _asnhex_getByteLengthOfL_AtObj(s, pos) {
if (s.substring(pos + 2, pos + 3) != '8') return 1;
var i = parseInt(s.substring(pos + 3, pos + 4));
if (i == 0) return -1; // length octet '80' indefinite length
if (0 < i && i < 10) return i + 1; // including '8?' octet;
return -2; // malformed format
}

function _asnhex_getHexOfL_AtObj(s, pos) {
var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
if (len < 1) return '';
return s.substring(pos + 2, pos + 2 + len * 2);
}

//
// getting ASN.1 length value at the position 'idx' of
// hexa decimal string 's'.
//
// f('3082025b02...', 0) ... 82025b ... ???
// f('020100', 0) ... 01 ... 1
// f('0203001...', 0) ... 03 ... 3
// f('02818003...', 0) ... 8180 ... 128
function _asnhex_getIntOfL_AtObj(s, pos) {
var hLength = _asnhex_getHexOfL_AtObj(s, pos);
if (hLength == '') return -1;
var bi;
if (parseInt(hLength.substring(0, 1)) < 8) {
bi = parseBigInt(hLength, 16);
} else {
bi = parseBigInt(hLength.substring(2), 16);
}
return bi.intValue();
}

//
// get ASN.1 value starting string position
// for ASN.1 object refered by index 'idx'.
//
function _asnhex_getStartPosOfV_AtObj(s, pos) {
var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
if (l_len < 0) return l_len;
return pos + (l_len + 1) * 2;
}

function _asnhex_getHexOfV_AtObj(s, pos) {
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
var len = _asnhex_getIntOfL_AtObj(s, pos);
return s.substring(pos1, pos1 + len * 2);
}

function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
var len = _asnhex_getIntOfL_AtObj(s, pos);
return pos1 + len * 2;
}

function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
var a = new Array();
var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
a.push(p0);

var len = _asnhex_getIntOfL_AtObj(h, pos);
var p = p0;
var k = 0;
while (1) {
var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
if (pNext == null || (pNext - p0 >= (len * 2))) break;
if (k >= 200) break;

a.push(pNext);
p = pNext;

k++;
}

return a;
}
71 changes: 71 additions & 0 deletions lib/kurushima-jsrsa/rsa-pem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
// to RSAKey class.
//
// version: 1.0 (2010-Jun-03)
//
// Copyright (c) 2010 Kenji Urushima ([email protected])
//
// This software is licensed under the terms of the MIT License.
// http://www.opensource.org/licenses/mit-license.php
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
//
// Depends on:
//
//
//
// _RSApem_pemToBase64(sPEM)
//
// removing PEM header, PEM footer and space characters including
// new lines from PEM formatted RSA private key string.
//
function _rsapem_pemToBase64(sPEMPrivateKey) {
var s = sPEMPrivateKey;
s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
s = s.replace("-----END RSA PRIVATE KEY-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
}

function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
var a = new Array();
var v1 = _asnhex_getStartPosOfV_AtObj(hPrivateKey, 0);
var n1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, v1);
var e1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, n1);
var d1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, e1);
var p1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, d1);
var q1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, p1);
var dp1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, q1);
var dq1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dp1);
var co1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dq1);
a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
return a;
}

function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
var v = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[0]);
var n = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[1]);
var e = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[2]);
var d = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[3]);
var p = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[4]);
var q = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[5]);
var dp = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[6]);
var dq = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[7]);
var co = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[8]);
var a = new Array();
a.push(v, n, e, d, p, q, dp, dq, co);
return a;
}

function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
var keyB64 = _rsapem_pemToBase64(keyPEM);
var keyHex = b64tohex(keyB64) // depends base64.js
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}

RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
155 changes: 155 additions & 0 deletions lib/kurushima-jsrsa/rsa-sign.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//
// rsa-sign.js - adding signing functions to RSAKey class.
//
//
// version: 1.0 (2010-Jun-03)
//
// Copyright (c) 2010 Kenji Urushima ([email protected])
//
// This software is licensed under the terms of the MIT License.
// http://www.opensource.org/licenses/mit-license.php
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.

//
// Depends on:
// function sha1.hex(s) of sha1.js
// jsbn.js
// jsbn2.js
// rsa.js
// rsa2.js
//

// keysize / pmstrlen
// 512 / 128
// 1024 / 256
// 2048 / 512
// 4096 / 1024

// As for _RSASGIN_DIHEAD values for each hash algorithm, see PKCS#1 v2.1 spec (p38).
var _RSASIGN_DIHEAD = [];
_RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414";
_RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420";
//_RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410";
//_RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410";
//_RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430";
//_RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440";
var _RSASIGN_HASHHEXFUNC = [];
_RSASIGN_HASHHEXFUNC['sha1'] = sha1.hex;
_RSASIGN_HASHHEXFUNC['sha256'] = sha256.hex;

// ========================================================================
// Signature Generation
// ========================================================================

function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
var pmStrLen = keySize / 4;
var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
var sHashHex = hashFunc(s);

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 _rsasign_signString(s, hashAlg) {
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return hexSign;
}

function _rsasign_signStringWithSHA1(s) {
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), 'sha1');
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return hexSign;
}

function _rsasign_signStringWithSHA256(s) {
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), 'sha256');
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return hexSign;
}

// ========================================================================
// Signature Verification
// ========================================================================

function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
var rsa = new RSAKey();
rsa.setPublic(hN, hE);
var biDecryptedSig = rsa.doPublic(biSig);
return biDecryptedSig;
}

function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
return hDigestInfo;
}

function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
for (var algName in _RSASIGN_DIHEAD) {
var head = _RSASIGN_DIHEAD[algName];
var len = head.length;
if (hDigestInfo.substring(0, len) == head) {
var a = [algName, hDigestInfo.substring(len)];
return a;
}
}
return [];
}

function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = _RSASIGN_HASHHEXFUNC[algName];
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}

function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
var biSig = parseBigInt(hSig, 16);
var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
this.n.toString(16),
this.e.toString(16));
return result;
}

function _rsasign_verifyString(sMsg, hSig) {
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_HASHHEXFUNC[algName];
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}

RSAKey.prototype.signString = _rsasign_signString;
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;

RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;

Loading

0 comments on commit 81d4bce

Please sign in to comment.