Comparing version 1.0.2 to 1.2.2
/* | ||
* Copyright (c) 2014, GMO GlobalSign | ||
* Copyright (c) 2015, Peculiar Ventures | ||
* All rights reserved. | ||
* | ||
* Author 2014, Yury Strozhevsky <www.strozhevsky.com>. | ||
* Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>. | ||
* | ||
@@ -7,0 +8,0 @@ * Redistribution and use in source and binary forms, with or without modification, |
/* | ||
* Copyright (c) 2014, GMO GlobalSign | ||
* Copyright (c) 2015, Peculiar Ventures | ||
* All rights reserved. | ||
* | ||
* Author 2014, Yury Strozhevsky <www.strozhevsky.com>. | ||
* Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>. | ||
* | ||
@@ -67,2 +68,15 @@ * Redistribution and use in source and binary forms, with or without modification, | ||
//************************************************************************************** | ||
in_window.org.pkijs.emptyObject = | ||
function() | ||
{ | ||
this.toJSON = function() | ||
{ | ||
return {}; | ||
}; | ||
this.toSchema = function() | ||
{ | ||
return {}; | ||
}; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getNames = | ||
@@ -81,2 +95,39 @@ function(arg) | ||
//************************************************************************************** | ||
in_window.org.pkijs.inheriteObjectFields = | ||
function(from) | ||
{ | ||
for(i in from.prototype) | ||
{ | ||
if(typeof from.prototype[i] === "function") | ||
continue; | ||
this[i] = from.prototype[i]; | ||
} | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getUTCDate = | ||
function(date) | ||
{ | ||
/// <summary>Making UTC date from local date</summary> | ||
/// <param name="date" type="Date">Date to convert from</param> | ||
var current_date = date; | ||
return new Date(current_date.getTime() + (current_date.getTimezoneOffset() * 60000)); | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.padNumber = | ||
function(input_number, full_length) | ||
{ | ||
var str = input_number.toString(10); | ||
var dif = full_length - str.length; | ||
var padding = new Array(dif); | ||
for(var i = 0; i < dif; i++) | ||
padding[i] = '0'; | ||
var padding_string = padding.join(''); | ||
return padding_string.concat(str); | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getValue = | ||
@@ -165,9 +216,14 @@ function(args, item, default_value) | ||
{ | ||
var crypto_temp = {}; | ||
//crypto_temp = window.msCrypto; | ||
//if(typeof crypto_temp === "undefined") | ||
//crypto_temp = window.polycrypt; | ||
//else | ||
crypto_temp = window.crypto.subtle; | ||
var crypto_temp; | ||
if("crypto" in in_window) | ||
{ | ||
// Apple Safari support | ||
if("webkitSubtle" in in_window.crypto) | ||
crypto_temp = in_window.crypto.webkitSubtle; | ||
if("subtle" in in_window.crypto) | ||
crypto_temp = in_window.crypto.subtle; | ||
} | ||
return crypto_temp; | ||
@@ -206,2 +262,1231 @@ } | ||
//************************************************************************************** | ||
in_window.org.pkijs.bufferFromHexCodes = | ||
function(hexString) | ||
{ | ||
/// <summary>Create an ArrayBuffer from string having hexdecimal codes</summary> | ||
/// <param name="hexString" type="String">String to create ArrayBuffer from</param> | ||
// #region Initial variables | ||
var stringLength = hexString.length; | ||
var resultBuffer = new ArrayBuffer(stringLength >> 1); | ||
var resultView = new Uint8Array(resultBuffer); | ||
var hex_map = {}; | ||
hex_map['0'] = 0x00; | ||
hex_map['1'] = 0x01; | ||
hex_map['2'] = 0x02; | ||
hex_map['3'] = 0x03; | ||
hex_map['4'] = 0x04; | ||
hex_map['5'] = 0x05; | ||
hex_map['6'] = 0x06; | ||
hex_map['7'] = 0x07; | ||
hex_map['8'] = 0x08; | ||
hex_map['9'] = 0x09; | ||
hex_map['A'] = 0x0A; | ||
hex_map['a'] = 0x0A; | ||
hex_map['B'] = 0x0B; | ||
hex_map['b'] = 0x0B; | ||
hex_map['C'] = 0x0C; | ||
hex_map['c'] = 0x0C; | ||
hex_map['D'] = 0x0D; | ||
hex_map['d'] = 0x0D; | ||
hex_map['E'] = 0x0E; | ||
hex_map['e'] = 0x0E; | ||
hex_map['F'] = 0x0F; | ||
hex_map['f'] = 0x0F; | ||
var j = 0; | ||
var temp = 0x00; | ||
// #endregion | ||
// #region Convert char-by-char | ||
for(var i = 0; i < stringLength; i++) | ||
{ | ||
if(!(i % 2)) | ||
temp = hex_map[hexString.charAt(i)] << 4; | ||
else | ||
{ | ||
temp |= hex_map[hexString.charAt(i)]; | ||
resultView[j] = temp; | ||
j++; | ||
} | ||
} | ||
// #endregion | ||
return resultBuffer; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getRandomValues = | ||
function(view) | ||
{ | ||
/// <param name="view" type="Uint8Array">New array which gives a length for random value</param> | ||
if("crypto" in in_window) | ||
return in_window.crypto.getRandomValues(view); | ||
else | ||
throw new Error("No support for Web Cryptography API"); | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getAlgorithmParameters = | ||
function(algorithmName, operation) | ||
{ | ||
/// <param name="algorithmName" type="String">Algorithm name to get common parameters for</param> | ||
/// <param name="operation" type="String">Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify"</param> | ||
var result = { | ||
algorithm: {}, | ||
usages: [] | ||
}; | ||
switch(algorithmName.toUpperCase()) | ||
{ | ||
case "RSASSA-PKCS1-V1_5": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "RSASSA-PKCS1-v1_5", | ||
modulusLength: 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
hash: { | ||
name: "SHA-256" | ||
}, | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
case "verify": | ||
case "sign": | ||
case "importkey": | ||
result = { | ||
algorithm: { | ||
name: "RSASSA-PKCS1-v1_5", | ||
hash: { | ||
name: "SHA-256" | ||
}, | ||
}, | ||
usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only | ||
}; | ||
break; | ||
case "exportkey": | ||
default: | ||
return { | ||
algorithm: { | ||
name: "RSASSA-PKCS1-v1_5" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "RSA-PSS": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "sign": | ||
case "verify": | ||
result = { | ||
algorithm: { | ||
name: "RSA-PSS", | ||
hash: { | ||
name: "SHA-1" | ||
}, | ||
saltLength: 20 | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "RSA-PSS", | ||
modulusLength: 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
hash: { | ||
name: "SHA-1" | ||
} | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
case "importkey": | ||
result = { | ||
algorithm: { | ||
name: "RSA-PSS", | ||
hash: { | ||
name: "SHA-1" | ||
}, | ||
}, | ||
usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only | ||
}; | ||
break; | ||
case "exportkey": | ||
default: | ||
return { | ||
algorithm: { | ||
name: "RSA-PSS" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "RSA-OAEP": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "encrypt": | ||
case "decrypt": | ||
result = { | ||
algorithm: { | ||
name: "RSA-OAEP", | ||
}, | ||
usages: ["encrypt", "decrypt"] | ||
}; | ||
break; | ||
break; | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "RSA-OAEP", | ||
modulusLength: 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
break; | ||
case "importkey": | ||
result = { | ||
algorithm: { | ||
name: "RSA-OAEP", | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}, | ||
usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8" | ||
}; | ||
break; | ||
case "exportkey": | ||
default: | ||
return { | ||
algorithm: { | ||
name: "RSA-OAEP" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "ECDSA": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "ECDSA", | ||
namedCurve: "P-256" | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
case "importkey": | ||
result = { | ||
algorithm: { | ||
name: "ECDSA", | ||
namedCurve: "P-256" | ||
}, | ||
usages: ["verify"] // "sign" for "pkcs8" | ||
}; | ||
break; | ||
case "verify": | ||
case "sign": | ||
result = { | ||
algorithm: { | ||
name: "ECDSA", | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}, | ||
usages: ["sign"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "ECDSA" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "ECDH": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "exportkey": | ||
case "importkey": | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "ECDH", | ||
namedCurve: "P-256" | ||
}, | ||
usages: ["deriveKey", "deriveBits"] | ||
}; | ||
break; | ||
case "derivekey": | ||
case "derivebits": | ||
result = { | ||
algorithm: { | ||
name: "ECDH", | ||
namedCurve: "P-256", | ||
public: [] // Must be a "publicKey" | ||
}, | ||
usages: ["encrypt", "decrypt"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "ECDH" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "AES-CTR": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "importkey": | ||
case "exportkey": | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "AES-CTR", | ||
length: 256 | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
break; | ||
case "decrypt": | ||
case "encrypt": | ||
result = { | ||
algorithm: { | ||
name: "AES-CTR", | ||
counter: new Uint8Array(16), | ||
length: 10 | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "AES-CTR" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "AES-CBC": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "importkey": | ||
case "exportkey": | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "AES-CBC", | ||
length: 256 | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
break; | ||
case "decrypt": | ||
case "encrypt": | ||
result = { | ||
algorithm: { | ||
name: "AES-CBC", | ||
iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "AES-CBC" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "AES-GCM": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "importkey": | ||
case "exportkey": | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "AES-GCM", | ||
length: 256 | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
break; | ||
case "decrypt": | ||
case "encrypt": | ||
result = { | ||
algorithm: { | ||
name: "AES-GCM", | ||
iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step | ||
}, | ||
usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] | ||
}; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "AES-GCM" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "AES-KW": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "importkey": | ||
case "exportkey": | ||
case "generatekey": | ||
case "wrapkey": | ||
case "unwrapkey": | ||
result = { | ||
algorithm: { | ||
name: "AES-KW", | ||
length: 256 | ||
}, | ||
usages: ["wrapKey", "unwrapKey"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "AES-KW" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "HMAC": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "sign": | ||
case "verify": | ||
result = { | ||
algorithm: { | ||
name: "HMAC", | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
case "importkey": | ||
case "exportkey": | ||
case "generatekey": | ||
result = { | ||
algorithm: { | ||
name: "HMAC", | ||
length: 10, | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}, | ||
usages: ["sign", "verify"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "HMAC" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "HKDF": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "derivekey": | ||
result = { | ||
algorithm: { | ||
name: "HKDF", | ||
hash: "SHA-256", | ||
salt: new Uint8Array(), | ||
info: new Uint8Array() | ||
}, | ||
usages: ["encrypt", "decrypt"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "HKDF" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
case "PBKDF2": | ||
switch(operation.toLowerCase()) | ||
{ | ||
case "derivekey": | ||
result = { | ||
algorithm: { | ||
name: "PBKDF2", | ||
hash: { name: "SHA-256" }, | ||
salt: new Uint8Array(), | ||
iterations: 1000 | ||
}, | ||
usages: ["encrypt", "decrypt"] | ||
}; | ||
break; | ||
default: | ||
return { | ||
algorithm: { | ||
name: "PBKDF2" | ||
}, | ||
usages: [] | ||
}; | ||
} | ||
break; | ||
default: | ||
; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getOIDByAlgorithm = | ||
function(algorithm) | ||
{ | ||
/// <summary>Get OID for each specific WebCrypto algorithm</summary> | ||
/// <param name="algorithm" type="Object">WebCrypto algorithm</param> | ||
var result = ""; | ||
switch(algorithm.name.toUpperCase()) | ||
{ | ||
case "RSASSA-PKCS1-V1_5": | ||
switch(algorithm.hash.name.toUpperCase()) | ||
{ | ||
case "SHA-1": | ||
result = "1.2.840.113549.1.1.5"; | ||
break; | ||
case "SHA-256": | ||
result = "1.2.840.113549.1.1.11"; | ||
break; | ||
case "SHA-384": | ||
result = "1.2.840.113549.1.1.12"; | ||
break; | ||
case "SHA-512": | ||
result = "1.2.840.113549.1.1.13"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "RSA-PSS": | ||
result = "1.2.840.113549.1.1.10"; | ||
break; | ||
case "RSA-OAEP": | ||
result = "1.2.840.113549.1.1.7"; | ||
break; | ||
case "ECDSA": | ||
switch(algorithm.hash.name.toUpperCase()) | ||
{ | ||
case "SHA-1": | ||
result = "1.2.840.10045.4.1"; | ||
break; | ||
case "SHA-256": | ||
result = "1.2.840.10045.4.3.2"; | ||
break; | ||
case "SHA-384": | ||
result = "1.2.840.10045.4.3.3"; | ||
break; | ||
case "SHA-512": | ||
result = "1.2.840.10045.4.3.4"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "ECDH": | ||
switch(algorithm.kdf.toUpperCase()) // Non-standard addition - hash algorithm of KDF function | ||
{ | ||
case "SHA-1": | ||
result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme | ||
break; | ||
case "SHA-256": | ||
result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme | ||
break; | ||
case "SHA-384": | ||
result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme | ||
break; | ||
case "SHA-512": | ||
result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "AES-CTR": | ||
break; | ||
case "AES-CBC": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.2"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.22"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.42"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "AES-CMAC": | ||
break; | ||
case "AES-GCM": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.6"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.26"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.46"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "AES-CFB": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.4"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.24"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.44"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "AES-KW": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.5"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.25"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.45"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "HMAC": | ||
switch(algorithm.hash.name.toUpperCase()) | ||
{ | ||
case "SHA-1": | ||
result = "1.2.840.113549.2.7"; | ||
break; | ||
case "SHA-256": | ||
result = "1.2.840.113549.2.9"; | ||
break; | ||
case "SHA-384": | ||
result = "1.2.840.113549.2.10"; | ||
break; | ||
case "SHA-512": | ||
result = "1.2.840.113549.2.11"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "DH": | ||
result = "1.2.840.113549.1.9.16.3.5"; | ||
break; | ||
case "SHA-1": | ||
result = "1.3.14.3.2.26"; | ||
break; | ||
case "SHA-256": | ||
result = "2.16.840.1.101.3.4.2.1"; | ||
break; | ||
case "SHA-384": | ||
result = "2.16.840.1.101.3.4.2.2"; | ||
break; | ||
case "SHA-512": | ||
result = "2.16.840.1.101.3.4.2.3"; | ||
break; | ||
case "CONCAT": | ||
break; | ||
case "HKDF": | ||
break; | ||
case "PBKDF2": | ||
result = "1.2.840.113549.1.5.12"; | ||
break; | ||
// #region Special case - OIDs for ECC curves | ||
case "P-256": | ||
result = "1.2.840.10045.3.1.7"; | ||
break; | ||
case "P-384": | ||
result = "1.3.132.0.34"; | ||
break; | ||
case "P-521": | ||
result = "1.3.132.0.35"; | ||
break; | ||
// #endregion | ||
default:; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getAlgorithmByOID = | ||
function(oid) | ||
{ | ||
/// <summary>Get WebCrypto algorithm by wel-known OID</summary> | ||
/// <param name="oid" type="String">Wel-known OID to search for</param> | ||
var result = {}; | ||
switch(oid) | ||
{ | ||
case "1.2.840.113549.1.1.5": | ||
result = { | ||
name: "RSASSA-PKCS1-v1_5", | ||
hash: { | ||
name: "SHA-1" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.1.1.11": | ||
result = { | ||
name: "RSASSA-PKCS1-v1_5", | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.1.1.12": | ||
result = { | ||
name: "RSASSA-PKCS1-v1_5", | ||
hash: { | ||
name: "SHA-384" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.1.1.13": | ||
result = { | ||
name: "RSASSA-PKCS1-v1_5", | ||
hash: { | ||
name: "SHA-512" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.1.1.10": | ||
result = { | ||
name: "RSA-PSS" | ||
}; | ||
break; | ||
case "1.2.840.113549.1.1.7": | ||
result = { | ||
name: "RSA-OAEP" | ||
}; | ||
break; | ||
case "1.2.840.10045.4.1": | ||
result = { | ||
name: "ECDSA", | ||
hash: { | ||
name: "SHA-1" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.10045.4.3.2": | ||
result = { | ||
name: "ECDSA", | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.10045.4.3.3": | ||
result = { | ||
name: "ECDSA", | ||
hash: { | ||
name: "SHA-384" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.10045.4.3.4": | ||
result = { | ||
name: "ECDSA", | ||
hash: { | ||
name: "SHA-512" | ||
} | ||
}; | ||
break; | ||
case "1.3.133.16.840.63.0.2": | ||
result = { | ||
name: "ECDH", | ||
kdf: "SHA-1" | ||
}; | ||
break; | ||
case "1.3.132.1.11.1": | ||
result = { | ||
name: "ECDH", | ||
kdf: "SHA-256" | ||
}; | ||
break; | ||
case "1.3.132.1.11.2": | ||
result = { | ||
name: "ECDH", | ||
kdf: "SHA-384" | ||
}; | ||
break; | ||
case "1.3.132.1.11.3": | ||
result = { | ||
name: "ECDH", | ||
kdf: "SHA-512" | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.2": | ||
result = { | ||
name: "AES-CBC", | ||
length: 128 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.22": | ||
result = { | ||
name: "AES-CBC", | ||
length: 192 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.42": | ||
result = { | ||
name: "AES-CBC", | ||
length: 256 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.6": | ||
result = { | ||
name: "AES-GCM", | ||
length: 128 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.26": | ||
result = { | ||
name: "AES-GCM", | ||
length: 192 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.46": | ||
result = { | ||
name: "AES-GCM", | ||
length: 256 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.4": | ||
result = { | ||
name: "AES-CFB", | ||
length: 128 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.24": | ||
result = { | ||
name: "AES-CFB", | ||
length: 192 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.44": | ||
result = { | ||
name: "AES-CFB", | ||
length: 256 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.5": | ||
result = { | ||
name: "AES-KW", | ||
length: 128 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.25": | ||
result = { | ||
name: "AES-KW", | ||
length: 192 | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.1.45": | ||
result = { | ||
name: "AES-KW", | ||
length: 256 | ||
}; | ||
break; | ||
case "1.2.840.113549.2.7": | ||
result = { | ||
name: "HMAC", | ||
hash: { | ||
name: "SHA-1" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.2.9": | ||
result = { | ||
name: "HMAC", | ||
hash: { | ||
name: "SHA-256" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.2.10": | ||
result = { | ||
name: "HMAC", | ||
hash: { | ||
name: "SHA-384" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.2.11": | ||
result = { | ||
name: "HMAC", | ||
hash: { | ||
name: "SHA-512" | ||
} | ||
}; | ||
break; | ||
case "1.2.840.113549.1.9.16.3.5": | ||
result = { | ||
name: "DH" | ||
}; | ||
break; | ||
case "1.3.14.3.2.26": | ||
result = { | ||
name: "SHA-1" | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.2.1": | ||
result = { | ||
name: "SHA-256" | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.2.2": | ||
result = { | ||
name: "SHA-384" | ||
}; | ||
break; | ||
case "2.16.840.1.101.3.4.2.3": | ||
result = { | ||
name: "SHA-512" | ||
}; | ||
break; | ||
case "1.2.840.113549.1.5.12": | ||
result = { | ||
name: "PBKDF2" | ||
}; | ||
break; | ||
// #region Special case - OIDs for ECC curves | ||
case "1.2.840.10045.3.1.7": | ||
result = { | ||
name: "P-256" | ||
}; | ||
break; | ||
case "1.3.132.0.34": | ||
result = { | ||
name: "P-384" | ||
}; | ||
break; | ||
case "1.3.132.0.35": | ||
result = { | ||
name: "P-521" | ||
}; | ||
break; | ||
// #endregion | ||
default:; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getHashAlgorithm = | ||
function(signatureAlgorithm) | ||
{ | ||
/// <summary>Getting hash algorithm by signature algorithm</summary> | ||
/// <param name="signatureAlgorithm" type="in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER">Signature algorithm</param> | ||
var result = ""; | ||
switch(signatureAlgorithm.algorithm_id) | ||
{ | ||
case "1.2.840.10045.4.1": // ecdsa-with-SHA1 | ||
case "1.2.840.113549.1.1.5": | ||
result = "SHA-1"; | ||
break; | ||
case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256 | ||
case "1.2.840.113549.1.1.11": | ||
result = "SHA-256"; | ||
break; | ||
case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384 | ||
case "1.2.840.113549.1.1.12": | ||
result = "SHA-384"; | ||
break; | ||
case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512 | ||
case "1.2.840.113549.1.1.13": | ||
result = "SHA-512"; | ||
break; | ||
case "1.2.840.113549.1.1.10": // RSA-PSS | ||
{ | ||
var params; | ||
try | ||
{ | ||
params = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signatureAlgorithm.algorithm_params }); | ||
if("hashAlgorithm" in params) | ||
{ | ||
var algorithm = in_window.org.pkijs.getAlgorithmByOID(params.hashAlgorithm.algorithm_id); | ||
if(("name" in algorithm) === false) | ||
return ""; | ||
result = algorithm.name; | ||
} | ||
else | ||
result = "SHA-1"; | ||
} | ||
catch(ex) | ||
{ | ||
} | ||
} | ||
break; | ||
default:; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.createCMSECDSASignature = | ||
function(signatureBuffer) | ||
{ | ||
/// <summary>Create CMS ECDSA signature from WebCrypto ECDSA signature</summary> | ||
/// <param name="signatureBuffer" type="ArrayBuffer">WebCrypto result of "sign" function</param> | ||
// #region Initial check for correct length | ||
if((signatureBuffer.byteLength % 2) != 0) | ||
return new ArrayBuffer(0); | ||
// #endregion | ||
// #region Initial variables | ||
var i = 0; | ||
var length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer | ||
var signatureView = new Uint8Array(signatureBuffer); | ||
var r_buffer = new ArrayBuffer(length); | ||
var r_view = new Uint8Array(r_buffer); | ||
var r_corrected_buffer; | ||
var r_corrected_view; | ||
var s_buffer = new ArrayBuffer(length); | ||
var s_view = new Uint8Array(s_buffer); | ||
var s_corrected_buffer; | ||
var s_corrected_view; | ||
// #endregion | ||
// #region Get "r" part of ECDSA signature | ||
for(; i < length; i++) | ||
r_view[i] = signatureView[i]; | ||
if(r_view[0] & 0x80) | ||
{ | ||
r_corrected_buffer = new ArrayBuffer(length + 1); | ||
r_corrected_view = new Uint8Array(r_corrected_buffer); | ||
r_corrected_view[0] = 0x00; | ||
for(var j = 0; j < length; j++) | ||
r_corrected_view[j + 1] = r_view[j]; | ||
} | ||
else | ||
{ | ||
r_corrected_buffer = r_buffer; | ||
r_corrected_view = r_view; | ||
} | ||
// #endregion | ||
// #region Get "s" part of ECDSA signature | ||
for(; i < signatureBuffer.byteLength; i++) | ||
s_view[i - length] = signatureView[i]; | ||
if(s_view[0] & 0x80) | ||
{ | ||
s_corrected_buffer = new ArrayBuffer(length + 1); | ||
s_corrected_view = new Uint8Array(s_corrected_buffer); | ||
s_corrected_view[0] = 0x00; | ||
for(var j = 0; j < length; j++) | ||
s_corrected_view[j + 1] = s_view[j]; | ||
} | ||
else | ||
{ | ||
s_corrected_buffer = s_buffer; | ||
s_corrected_view = s_view; | ||
} | ||
// #endregion | ||
// #region Create ASN.1 structure of CMS ECDSA signature | ||
var r_integer = new in_window.org.pkijs.asn1.INTEGER(); | ||
r_integer.value_block.is_hex_only = true; | ||
r_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(r_corrected_buffer); | ||
var s_integer = new in_window.org.pkijs.asn1.INTEGER(); | ||
s_integer.value_block.is_hex_only = true; | ||
s_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(s_corrected_buffer); | ||
var asn1 = new in_window.org.pkijs.asn1.SEQUENCE({ | ||
value: [ | ||
r_integer, | ||
s_integer | ||
] | ||
}); | ||
// #endregion | ||
return asn1.toBER(false); | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.createECDSASignatureFromCMS = | ||
function(cmsSignature) | ||
{ | ||
/// <summary>Create a single ArrayBuffer from CMS ECDSA signature</summary> | ||
/// <param name="cmsSignature" type="in_window.org.pkijs.asn1.SEQUENCE">ASN.1 SEQUENCE contains CMS ECDSA signature</param> | ||
// #region Initial variables | ||
var length = 0; | ||
var r_start = 0; | ||
var s_start = 0; | ||
var r_length = cmsSignature.value_block.value[0].value_block.value_hex.byteLength; | ||
var s_length = cmsSignature.value_block.value[1].value_block.value_hex.byteLength; | ||
// #endregion | ||
// #region Get length of final "ArrayBuffer" | ||
var r_view = new Uint8Array(cmsSignature.value_block.value[0].value_block.value_hex); | ||
if((r_view[0] === 0x00) && (r_view[1] & 0x80)) | ||
{ | ||
length = r_length - 1; | ||
r_start = 1; | ||
} | ||
else | ||
length = r_length; | ||
var s_view = new Uint8Array(cmsSignature.value_block.value[1].value_block.value_hex); | ||
if((s_view[0] === 0x00) && (s_view[1] & 0x80)) | ||
{ | ||
length += s_length - 1; | ||
s_start = 1; | ||
} | ||
else | ||
length += s_length; | ||
// #endregion | ||
// #region Copy values from CMS ECDSA signature | ||
var result = new ArrayBuffer(length); | ||
var result_view = new Uint8Array(result); | ||
for(var i = r_start; i < r_length; i++) | ||
result_view[i - r_start] = r_view[i]; | ||
for(var i = s_start; i < s_length; i++) | ||
result_view[i - s_start + r_length - r_start] = s_view[i]; | ||
// #endregion | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getEncryptionAlgorithm = | ||
function(algorithm) | ||
{ | ||
/// <summary>Get encryption algorithm OID by WebCrypto algorithm's object</summary> | ||
/// <param name="algorithm" type="WebCryptoAlgorithm">WebCrypto algorithm object</param> | ||
var result = ""; | ||
switch(algorithm.name.toUpperCase()) | ||
{ | ||
case "AES-CBC": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.2"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.22"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.42"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
case "AES-GCM": | ||
switch(algorithm.length) | ||
{ | ||
case 128: | ||
result = "2.16.840.1.101.3.4.1.6"; | ||
break; | ||
case 192: | ||
result = "2.16.840.1.101.3.4.1.26"; | ||
break; | ||
case 256: | ||
result = "2.16.840.1.101.3.4.1.46"; | ||
break; | ||
default:; | ||
} | ||
break; | ||
default:; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
in_window.org.pkijs.getAlgorithmByEncryptionOID = | ||
function(oid) | ||
{ | ||
/// <summary>Get encryption algorithm name by OID</summary> | ||
/// <param name="oid" type="String">OID of encryption algorithm</param> | ||
var result = ""; | ||
switch(oid) | ||
{ | ||
case "2.16.840.1.101.3.4.1.2": | ||
case "2.16.840.1.101.3.4.1.22": | ||
case "2.16.840.1.101.3.4.1.42": | ||
result = "AES-CBC"; | ||
break; | ||
case "2.16.840.1.101.3.4.1.6": | ||
case "2.16.840.1.101.3.4.1.26": | ||
case "2.16.840.1.101.3.4.1.46": | ||
result = "AES-GCM"; | ||
break; | ||
default:; | ||
} | ||
return result; | ||
} | ||
//************************************************************************************** | ||
// #endregion | ||
@@ -208,0 +1493,0 @@ //************************************************************************************** |
@@ -8,3 +8,3 @@ { | ||
"description": "ASN1js is a pure JavaScript library implementing this standard. ASN.1 is the basis of all X.509 related data structures and numerous other protocols used on the web", | ||
"version": "1.0.2", | ||
"version": "1.2.2", | ||
"repository": { | ||
@@ -11,0 +11,0 @@ "type": "git", |
@@ -11,2 +11,3 @@ ## ASN1js | ||
* [ASN1js][] is a "base layer" for full-featured JS library [PKIjs][], which is using Web Cryptography API and has all classes, neccessary to work with PKI-related data; | ||
* Fully object-oriented library. Inhiritence is using everywhere inside the lib; | ||
@@ -133,6 +134,6 @@ * Working with HTML5 data objects (ArrayBuffer, Uint8Array etc.); | ||
!!! WARNING !!! | ||
Currently there is no "polyfill" of WebCrypto in Node.js. Thus you will not be able to use signature / verification features of PKIjs in Node.js programs. | ||
**!!! WARNING !!! ** | ||
**Currently there is no "polyfill" of WebCrypto in Node.js. Thus you will not be able to use signature / verification features of PKIjs in Node.js programs.** | ||
In order to use PKIjs you will also need [ASN1js][] plus [node.extend](https://www.npmjs.com/package/node.extend) package. | ||
In order to use [PKIjs][] you will also need [ASN1js][] plus [node.extend](https://www.npmjs.com/package/node.extend) package. | ||
```javascript | ||
@@ -175,5 +176,6 @@ var merge = require("node.extend"); | ||
Copyright (c) 2014, [GMO GlobalSign](http://www.globalsign.com/) | ||
Copyright (c) 2015, [Peculiar Ventures](http://peculiarventures.com/) | ||
All rights reserved. | ||
Author 2014, [Yury Strozhevsky](http://www.strozhevsky.com/). | ||
Author 2014-2015, [Yury Strozhevsky](http://www.strozhevsky.com/). | ||
@@ -180,0 +182,0 @@ Redistribution and use in source and binary forms, with or without modification, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
299401
6048
211