├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── SECURITY.md ├── definitions ├── IE11PromiseWrapper.d.ts ├── msrCrypto.d.ts └── msrcrypto.intellisense.js ├── gulpfile.js ├── lib ├── IE11PromiseWrapper.js ├── msrcrypto.js └── msrcrypto.min.js ├── msrcrypto.code-workspace ├── package-lock.json ├── package.json ├── scripts ├── aes-cbc.js ├── aes-gcm.js ├── aes-kw.js ├── aes.js ├── asn1.js ├── bundleHead.js ├── bundleTail.js ├── concat.js ├── cryptoECC.js ├── cryptoMath.js ├── curves_BN.js ├── curves_NIST.js ├── curves_NUMS.js ├── curves_NUMS_old.js ├── ecdh.js ├── ecdsa.js ├── entropy.js ├── global.js ├── hkdf-ctr.js ├── hkdf.js ├── hmac.js ├── jwk.js ├── kdf.js ├── operations.js ├── pbkdf2.js ├── prime.js ├── qunit │ ├── qunit-1.23.1.css │ └── qunit-1.23.1.js ├── random.js ├── rsa-base.js ├── rsa-oaep.js ├── rsa-pkcs1.js ├── rsa-pss.js ├── rsa.js ├── sha.js ├── sha1.js ├── sha256.js ├── sha512.js ├── subtle.js ├── subtle │ ├── head.js │ ├── keyManager.js │ ├── operations.js │ ├── promises.js │ ├── subtleInterface.js │ ├── syncWorker.js │ ├── tail.js │ └── workerManager.js ├── testInterface.js ├── testVectors │ ├── tv_aes_cbc.js │ ├── tv_aes_gcm.js │ ├── tv_aes_kw.js │ ├── tv_concatkdf.js │ ├── tv_ecdh.js │ ├── tv_ecdsa.js │ ├── tv_hkdf.js │ ├── tv_hkdfCtr.js │ ├── tv_hmac.js │ ├── tv_pbkdf2.js │ ├── tv_prng.js │ ├── tv_rsa_es.js │ ├── tv_rsa_oaep.js │ ├── tv_rsa_pss.js │ ├── tv_rsa_ssa.js │ └── tv_sha2.js ├── tests │ ├── Test.Aes.Cbc.js │ ├── Test.Aes.Gcm.js │ ├── Test.Aes.Kw.js │ ├── Test.ConcatKdf.js │ ├── Test.Ecdh.js │ ├── Test.Ecdsa.js │ ├── Test.Encoding.js │ ├── Test.Hkdf.js │ ├── Test.HkdfCtr.js │ ├── Test.Hmac.js │ ├── Test.Pbkdf2.js │ ├── Test.Prng.js │ ├── Test.Promise.js │ ├── Test.Rsa.Es.js │ ├── Test.Rsa.Oaep.js │ ├── Test.Rsa.Pss.js │ ├── Test.Rsa.Ssa.js │ ├── Test.Sha2.js │ ├── Test.Shared.js │ └── Test.WrapKey.js ├── utilities.js ├── worker.js └── wrapKey.js └── tests ├── CryptoECCTests.html ├── CryptoMathTests.html └── SubtleTests.html /.gitignore: -------------------------------------------------------------------------------- 1 | # npm packages loaded on user's system 2 | node_modules/ 3 | 4 | # This gets re-built by gulp with each build. 5 | scripts/subtle.js 6 | 7 | /.history 8 | /.DS_Store 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": {}, 3 | "cSpell.words": [ 4 | "Ciphertext", 5 | "HMAC", 6 | "NIST", 7 | "PRNG", 8 | "Precomputation", 9 | "bitlength", 10 | "gctr", 11 | "msrcrypto", 12 | "qunit" 13 | ] 14 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "gulp", 8 | "task": "default", 9 | "problemMatcher": [], 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | } 14 | }, 15 | { 16 | "type": "npm", 17 | "script": "install", 18 | "problemMatcher": [] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /definitions/IE11PromiseWrapper.d.ts: -------------------------------------------------------------------------------- 1 | declare module "IE11PromiseWrapper" { 2 | var ieE11PromiseWrapper: Crypto /*lib.d.ts*/ 3 | export = ieE11PromiseWrapper; 4 | } -------------------------------------------------------------------------------- /definitions/msrCrypto.d.ts: -------------------------------------------------------------------------------- 1 | // Crypto from lib.d.ts 2 | declare module "msrCrypto" { 3 | var msrCrypto: Crypto; 4 | export = msrCrypto; 5 | } 6 | 7 | // Extend default Crypto from lib.d.ts to add msrCrypto extras 8 | interface Crypto { 9 | initPrng(entropyData: ArrayLike): void; 10 | toBase64(data: ArrayLike | ArrayBuffer, toBase64Url?: boolean): string; 11 | fromBase64(data: string): ArrayLike; 12 | textToBytes(text: string): ArrayLike; 13 | bytesToText(bytes: ArrayLike): String; 14 | } 15 | 16 | // Extend default Algorithm from lib.d.ts 17 | //interface Algorithm { 18 | // salt?: ArrayLike, 19 | // namedCurve?: string, 20 | // iv?: ArrayLike, 21 | // tagLength?: number, 22 | // additionalData?: ArrayLike, 23 | // hash?: { name: string }, 24 | // length?: number, 25 | // stream?: boolean 26 | //} 27 | 28 | // Support msrCrypto streaming with new StreamObject 29 | interface StreamObject { 30 | process(data: ArrayBuffer | ArrayLike): PromiseLike | void>; 31 | finish(): PromiseLike>; 32 | abort(): PromiseLike; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const gulp = require("gulp"); 3 | const concat = require("gulp-concat"); 4 | const strip = require("gulp-strip-comments"); 5 | const header = require("gulp-header"); 6 | const beautify = require("gulp-beautify"); 7 | const minify = require("gulp-minify"); 8 | const clean = require("gulp-clean"); 9 | const removeTest = require("gulp-strip-code"); 10 | 11 | const outputFiles = [ 12 | "lib/msrcrypto.js", 13 | "lib/msrcrypto.min.js" 14 | ]; 15 | 16 | const subtleBuild = [ 17 | "scripts/subtle/head.js", 18 | "scripts/subtle/syncWorker.js", 19 | "scripts/subtle/operations.js", 20 | "scripts/subtle/keyManager.js", 21 | "scripts/subtle/workerManager.js", 22 | "scripts/subtle/subtleInterface.js", 23 | "scripts/subtle/tail.js" 24 | ]; 25 | 26 | const fullBuild = [ 27 | "scripts/bundleHead.js", 28 | "scripts/operations.js", 29 | "scripts/global.js", 30 | "scripts/utilities.js", 31 | "scripts/asn1.js", 32 | "scripts/worker.js", 33 | "scripts/jwk.js", 34 | "scripts/cryptoMath.js", 35 | "scripts/cryptoECC.js", 36 | "scripts/curves_NIST.js", 37 | "scripts/curves_BN.js", 38 | "scripts/curves_NUMS.js", 39 | "scripts/sha.js", 40 | "scripts/sha1.js", 41 | "scripts/sha256.js", 42 | "scripts/sha512.js", 43 | "scripts/hmac.js", 44 | "scripts/aes.js", 45 | "scripts/aes-cbc.js", 46 | "scripts/aes-gcm.js", 47 | "scripts/aes-kw.js", 48 | "scripts/random.js", 49 | "scripts/entropy.js", 50 | "scripts/prime.js", 51 | "scripts/rsa-base.js", 52 | "scripts/rsa-oaep.js", 53 | "scripts/rsa-pkcs1.js", 54 | "scripts/rsa-pss.js", 55 | "scripts/rsa.js", 56 | "scripts/concat.js", 57 | "scripts/pbkdf2.js", 58 | "scripts/hkdf.js", 59 | "scripts/hkdf-ctr.js", 60 | "scripts/ecdh.js", 61 | "scripts/ecdsa.js", 62 | "scripts/subtle.js", 63 | "scripts/wrapKey.js", 64 | "scripts/bundleTail.js", 65 | "scripts/subtle/promises.js" 66 | ]; 67 | 68 | const aesBuild = [ 69 | "scripts/bundleHead.js", 70 | "scripts/operations.js", 71 | "scripts/global.js", 72 | "scripts/utilities.js", 73 | "scripts/worker.js", 74 | "scripts/jwk.js", 75 | "scripts/sha.js", 76 | "scripts/sha1.js", 77 | "scripts/sha256.js", 78 | "scripts/sha512.js", 79 | "scripts/hmac.js", 80 | "scripts/aes.js", 81 | "scripts/aes-cbc.js", 82 | "scripts/aes-gcm.js", 83 | "scripts/random.js", 84 | "scripts/entropy.js", 85 | "scripts/subtle.js", 86 | "scripts/wrapKey.js", 87 | "scripts/bundleTail.js", 88 | "scripts/subtle/promises.js" 89 | ]; 90 | 91 | const testBuild = fullBuild.concat([ 92 | "scripts/testInterface.js" 93 | ]); 94 | 95 | // Delete the old output files before building. 96 | function cleanBuild() { 97 | return gulp.src(outputFiles, { read: false, allowEmpty: true }) 98 | .pipe(clean()); 99 | } 100 | 101 | // Build the subtle.js file from a set of individual files. 102 | function subtle() { 103 | return gulp.src(subtleBuild) 104 | .pipe(concat("subtle.js")) // concatenate scripts into single UMD module 105 | .pipe(strip({ trim: true })) // strip the comments out 106 | .pipe(beautify.js({ indent_size: 4, no_preserve_newlines: true })) // format the code 107 | .pipe(header(fs.readFileSync("LICENSE", "utf8"))) // add a copyright/license header 108 | .pipe(gulp.dest("scripts")); // write the file to the lib folder 109 | } 110 | 111 | // Concat the files into a single bundle. 112 | function bundle() { 113 | return gulp.src(fullBuild) 114 | .pipe(concat("msrcrypto.js")) // concatenate scripts into single UMD module 115 | .pipe(gulp.dest("lib")); // write the file to the lib folder 116 | } 117 | 118 | // Clean and format the new bundle. 119 | function format() { 120 | return gulp.src( 121 | [ 122 | "lib/msrcrypto.js" 123 | ]) 124 | .pipe(removeTest({ start_comment: "debug-block", end_comment: "end-debug-block" })) // strip out test/debug code 125 | .pipe(clean()) 126 | .pipe(strip({ trim: true })) // strip the comments out 127 | .pipe(beautify.js({ indent_size: 4, no_preserve_newlines: true })) // format the code 128 | .pipe(gulp.dest("lib")); // write the file to the lib folder 129 | } 130 | 131 | // Minify the new bundle to a .min.js file. 132 | function minifyBundle() { 133 | return gulp.src( 134 | [ 135 | "lib/msrcrypto.js" 136 | ]) 137 | .pipe(minify({ 138 | ext: { min: ".min.js" }, 139 | // Fix IE8 catch issue in Promises 140 | compress: { properties: false } 141 | })) 142 | .pipe(gulp.dest("lib")); // write the file to the lib folder 143 | } 144 | 145 | // Add the copyright/license header to output files. 146 | function addCopyrightHeaders() { 147 | return gulp.src(outputFiles) 148 | .pipe(header(fs.readFileSync("LICENSE", "utf8"))) // add a copyright/license header 149 | .pipe(gulp.dest("lib")); // write the file to the lib folder 150 | } 151 | 152 | gulp.task("default", gulp.series(cleanBuild, subtle, bundle, format, minifyBundle, addCopyrightHeaders)); 153 | 154 | // To run the default: >.\node_modules\.bin\gulp 155 | -------------------------------------------------------------------------------- /msrcrypto.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "editor.formatOnPaste": true, 9 | "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 10 | "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false 11 | } 12 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@microsoft/msrcrypto", 3 | "version": "1.6.6", 4 | "description": "MSR JavaScript Cryptography Library", 5 | "license": "Apache-2.0", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/microsoft/MSR-JavaScript-Crypto.git" 9 | }, 10 | "scripts": { 11 | "build": "gulp" 12 | }, 13 | "devDependencies": { 14 | "@types/gulp": "^4.0.9", 15 | "@types/gulp-concat": "0.0.32", 16 | "@types/gulp-header": "^2.0.1", 17 | "@types/gulp-strip-comments": "^2.5.1", 18 | "gulp": "^4.0.2", 19 | "gulp-beautify": "^3.0.0", 20 | "gulp-clean": "^0.4.0", 21 | "gulp-concat": "^2.6.1", 22 | "gulp-header": "^2.0.9", 23 | "gulp-minify": "^3.1.0", 24 | "gulp-strip-code": "^0.1.4", 25 | "gulp-strip-comments": "^2.5.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /scripts/asn1.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: no-bitwise 20 | 21 | var asn1 = (function () { 22 | var asn1Types = { 23 | 0x00: "CUSTOM", 24 | 0x01: "BOOLEAN", 25 | 0x02: "INTEGER", 26 | 0x03: "BIT STRING", 27 | 0x04: "OCTET STRING", 28 | 0x05: "NULL", 29 | 0x06: "OBJECT IDENTIFIER", 30 | 0x10: "SEQUENCE", 31 | 0x11: "SET", 32 | 0x13: "PRINTABLE STRING", 33 | 0x17: "UTCTime" 34 | }; 35 | 36 | var asn1Classes = { 37 | 0x00: "UNIVERSAL", 38 | 0x01: "APPLICATION", 39 | 0x02: "Context-Defined", 40 | 0x03: "PRIVATE" 41 | }; 42 | 43 | function parse(bytes, force) { 44 | force = !!force; 45 | 46 | var type = asn1Types[bytes[0] & 0x1f], 47 | dataLen = bytes[1], 48 | i = 0, 49 | constructed = !!(bytes[0] & 0x20), 50 | //_class = asn1Classes[bytes[0] >>> 6], 51 | remainder, 52 | child, 53 | header; 54 | 55 | if (dataLen & 0x80) { 56 | // length > 127 57 | for (i = 0, dataLen = 0; i < (bytes[1] & 127); i++) { 58 | dataLen = (dataLen << 8) + bytes[2 + i]; 59 | } 60 | } 61 | 62 | header = 2 + i; 63 | 64 | if (type === undefined || dataLen > bytes.length) { 65 | return null; 66 | } 67 | 68 | var obj = constructed ? [] : {}; 69 | 70 | obj.type = type; 71 | obj.header = header; 72 | //obj.length = dataLen + header; 73 | obj.data = bytes.slice(0, dataLen + header); 74 | //obj.class = _class; 75 | 76 | if (constructed || force) { 77 | if (obj.type === "BIT STRING" && bytes[header] === 0) { 78 | i++; 79 | } 80 | remainder = bytes.slice(header, obj.data.length); 81 | //obj.children = []; 82 | while (remainder.length > 0) { 83 | child = parse(remainder); 84 | if (child === null) { 85 | break; 86 | } 87 | //obj.children.push(child); 88 | obj.push(child); 89 | remainder = remainder.slice(child.data.length); 90 | } 91 | } 92 | return obj; 93 | } 94 | 95 | function encode(node) { 96 | var INTEGER = 0x02, 97 | BIT_STRING = 0x03, 98 | OCTET_STRING = 0x04, 99 | NULL = 0x05, 100 | OBJECT_IDENTIFIER = 0x06, 101 | SEQUENCE = 0x10, 102 | 103 | APPLICATION = 0xA0, //01...... 104 | CONSTRUCTED = 0x20; //..1..... 105 | 106 | if (node.hasOwnProperty("INTEGER")) { 107 | var val = node.INTEGER; 108 | if (msrcryptoUtilities.isInteger(val)) val = intToBytes(val); 109 | if (val[0] & 128) val.unshift(0); 110 | var result = [INTEGER].concat(encodeLength(val), val); 111 | return result; 112 | } 113 | 114 | if (node.hasOwnProperty("OCTET STRING")) { 115 | var val = node["OCTET STRING"]; 116 | if (!(val instanceof Array)) val = encode(val); 117 | var result = [OCTET_STRING].concat(encodeLength(val), val); 118 | return result; 119 | } 120 | 121 | if (node.hasOwnProperty("BIT STRING")) { 122 | var val = node["BIT STRING"]; 123 | if (!(val instanceof Array)) val = encode(val); 124 | val.unshift(0); 125 | var result = [BIT_STRING].concat(encodeLength(val), val); 126 | return result; 127 | } 128 | 129 | if (node.hasOwnProperty("NULL")) { 130 | return [NULL, 0]; 131 | } 132 | 133 | if (node.hasOwnProperty("OBJECT IDENTIFIER")) { 134 | var val = encodeOid(node["OBJECT IDENTIFIER"]); 135 | var result = [OBJECT_IDENTIFIER].concat(encodeLength(val), val); 136 | return result; 137 | } 138 | 139 | if (node.hasOwnProperty("SEQUENCE")) { 140 | var nodes = node.SEQUENCE; 141 | var val = []; 142 | for (var i = 0; i < nodes.length; i++) { 143 | val = val.concat(encode(nodes[i])); 144 | } 145 | var result = [SEQUENCE | CONSTRUCTED].concat(encodeLength(val), val); 146 | return result; 147 | } 148 | 149 | if (node.hasOwnProperty("APPLICATION")) { 150 | var nodes = node.APPLICATION; 151 | var structured = isNaN(parseInt(nodes[0])) ? CONSTRUCTED : 0; 152 | var tag = node.tag; 153 | var val = structured ? [] : node.APPLICATION; 154 | 155 | if(structured) { 156 | for (var i = 0; i < nodes.length; i++) { 157 | val = val.concat(encode(nodes[i])); 158 | } 159 | } 160 | 161 | var result = [APPLICATION | structured | tag].concat(encodeLength(val), val); 162 | 163 | return result; 164 | } 165 | 166 | throw new Error("unsupported asn.1 type"); 167 | } 168 | 169 | function encodeLength(bytes) { 170 | var len = bytes.length; 171 | if (len <= 127 /*0x80*/) return [len]; 172 | var result = intToBytes(len); 173 | result.unshift(result.length | 128); 174 | return result; 175 | } 176 | 177 | function intToBytes(int) { 178 | var result = []; 179 | if(int === 0) return [0]; 180 | while (int > 0) { 181 | result.unshift(int & 255); 182 | int >>>= 8; 183 | } 184 | return result; 185 | } 186 | 187 | function encodeOid(text) { 188 | // part-0 and part-1 are encoded in the first byte 189 | var parts = text.split("."); 190 | var result = [parseInt(parts[0] * 40 + parseInt(parts[1]))]; 191 | 192 | // the remaining parts are encoded as base-128 with bit 7=1 except for the last byte 193 | for (var i = 2; i < parts.length; i++) { 194 | var val = parseInt(parts[i]); 195 | 196 | var bytes = []; 197 | while (val > 0) { 198 | bytes.push((val & 127) | 128); 199 | val = val >>> 7; 200 | } 201 | bytes[0] = bytes[0] & 127; 202 | 203 | result = result.concat(bytes.reverse()); 204 | } 205 | return result; 206 | } 207 | 208 | 209 | function toString(objTree, indent) { 210 | var output = 211 | new Array(indent + 1).join(" ") + 212 | objTree.type + 213 | " (" + 214 | objTree.length + 215 | ") " + 216 | bytesToHexString(objTree.data).substring(0, 16) + 217 | "\n"; 218 | 219 | if (!objTree.children) { 220 | return output; 221 | } 222 | 223 | for (var i = 0; i < objTree.children.length; i++) { 224 | output += toString(objTree.children[i], indent + 4) + ""; 225 | } 226 | 227 | return output; 228 | } 229 | 230 | 231 | return { 232 | parse: parse, 233 | encode: encode, 234 | toString: function (objTree) { 235 | return toString(objTree, 0); 236 | } 237 | }; 238 | })(); 239 | -------------------------------------------------------------------------------- /scripts/bundleHead.js: -------------------------------------------------------------------------------- 1 | 2 | //******************************************************************************* 3 | // 4 | // Copyright 2020 Microsoft 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | // 18 | //******************************************************************************* 19 | 20 | "use strict"; 21 | 22 | var msrCryptoVersion = "1.6.6"; 23 | 24 | // UMD wrapper 25 | (function(root, factory) { 26 | 27 | if (typeof define === "function" && define.amd) { 28 | define([], function() { 29 | return (root.msrCrypto = factory(root)); 30 | }); 31 | } else if (typeof exports === "object") { 32 | module.exports = factory(root); 33 | } else { 34 | root.msrCrypto = factory(root); 35 | } 36 | 37 | }(this, function(global) { 38 | 39 | // tslint:disable-next-line: no-bitwise 40 | global = global || {}; 41 | 42 | var msrCrypto = function() { 43 | -------------------------------------------------------------------------------- /scripts/bundleTail.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var publicMethods = { 20 | 21 | /// Microsoft Research Javascript Crypto Library Subtle interface. 22 | subtle: msrcryptoSubtle ? msrcryptoSubtle.publicMethods : null, 23 | 24 | getRandomValues: function(array) { 25 | /// 26 | /// Places cryptographically random values into the given array. 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// Places cryptographically random values into the given array. 32 | /// 33 | /// Returns ArrayBufferView if supported. 34 | /// 35 | 36 | var i; 37 | var randomValues = msrcryptoPseudoRandom.getBytes(array.length); 38 | for (i = 0; i < array.length; i += 1) { 39 | array[i] = randomValues[i]; 40 | } 41 | return array; 42 | }, 43 | 44 | initPrng: function(entropyData) { 45 | /// 46 | /// Add entropy to the PRNG. 47 | /// Entropy input to seed or reseed the PRNG. 48 | /// 49 | 50 | var entropyDataType = Object.prototype.toString.call(entropyData); 51 | 52 | if (entropyDataType !== "[object Array]" && entropyDataType !== "[object Uint8Array]") { 53 | throw new Error("entropyData must be a Array or Uint8Array"); 54 | } 55 | 56 | // Mix the user-provided entropy into the entropy pool - only in the main thread. 57 | entropyPool && entropyPool.reseed(entropyData); 58 | 59 | // Reseed the PRNG that was initialized below 60 | msrcryptoPseudoRandom.reseed(entropyPool.read(48)); 61 | fprngEntropyProvided = true; 62 | }, 63 | 64 | toBase64: function(data, base64Url) { 65 | /// 66 | /// Convert Array of bytes to a Base64 string. 67 | /// Byte values (numbers 0-255) 68 | /// Return Base64Url encoding (this is different from Base64 encoding.) 69 | /// 70 | /// 71 | /// 72 | /// Convert Array of bytes to a Base64 string. 73 | /// Byte values (numbers 0-255) 74 | /// Return Base64Url encoding (this is different from Base64 encoding.) 75 | /// 76 | /// 77 | /// 78 | /// Convert Array of bytes to a Base64 string. 79 | /// Byte values (numbers 0-255) 80 | /// Return Base64Url encoding (this is different from Base64 encoding.) 81 | /// 82 | /// 83 | 84 | return msrcryptoUtilities.toBase64(data, base64Url); 85 | }, 86 | 87 | fromBase64: function(base64String) { 88 | /// 89 | /// Decode a Base64/Base64Url encoded string to an Array of bytes. 90 | /// Base64 encoded string. 91 | /// 92 | /// 93 | return msrcryptoUtilities.fromBase64(base64String); 94 | }, 95 | 96 | textToBytes: function(text) { 97 | /// 98 | /// Convert UTF-8/ASCII to an Array of bytes. 99 | /// UTF-8/ASCII text 100 | /// 101 | /// 102 | return msrcryptoUtilities.stringToBytes(text); 103 | }, 104 | 105 | bytesToText: function(byteArray) { 106 | /// 107 | /// Convert an Array of bytes to UTF-8/ASCII text. 108 | /// Array of bytes. 109 | /// 110 | /// 111 | /// 112 | /// Convert a TypedArray bytes to UTF-8/ASCII text. 113 | /// Array of bytes. 114 | /// 115 | /// 116 | /// 117 | /// Convert an ArrayBuffer of bytes to UTF-8/ASCII text. 118 | /// Array of bytes. 119 | /// 120 | /// 121 | return msrcryptoUtilities.bytesToString(byteArray); 122 | }, 123 | 124 | asn1 : asn1, 125 | 126 | /// URL of the this msrCrypto script. 127 | url : scriptUrl, 128 | 129 | /// Library version 130 | version: msrCryptoVersion, 131 | 132 | useWebWorkers : function(useWebWorkers) { 133 | /// 134 | /// Enable the use of web workers if supported by the browser. If the attempt to use web workers fails, web workers will remain disabled. 135 | /// true to use web workers. false to disable (default) 136 | /// 137 | return msrcryptoSubtle ? msrcryptoSubtle.internalMethods.useWebWorkers(useWebWorkers) : null; 138 | } 139 | }; 140 | 141 | /* debug-block */ 142 | // Expose the math library if present 143 | if (typeof cryptoMath !== "undefined") { 144 | publicMethods.cryptoMath = cryptoMath; 145 | } 146 | 147 | if (typeof testInterface !== "undefined") { 148 | publicMethods.testInterface = testInterface; 149 | } 150 | /* end-debug-block */ 151 | 152 | // Initialize the main entropy pool instance on the main thread, only. 153 | // The main thread creates and manages the central entropy pool. 154 | // All workers would have their own PRNG instance initialized by injected entropy from the main thread. 155 | var entropyPool; 156 | 157 | //if (!runningInWorkerInstance) { 158 | entropyPool = entropyPool || new MsrcryptoEntropy(global); 159 | 160 | // Initialize the entropy pool in the main thread. 161 | // There is only one entropy pool. 162 | entropyPool.init(); 163 | var localEntropy = entropyPool.read(48); // 48 is from SP800-90A; could be longer 164 | msrcryptoPseudoRandom.init(localEntropy); 165 | //} 166 | 167 | return publicMethods; 168 | 169 | } 170 | 171 | return msrCrypto(); 172 | 173 | })); 174 | -------------------------------------------------------------------------------- /scripts/concat.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | /// key derivation function from RFC 5869A https://www.ietf.org/rfc/rfc5869.txt 20 | var msrcryptoConcatKdf = (function () { 21 | 22 | function deriveBits(p) { 23 | 24 | var hashName = p.algorithm.hash.name, 25 | hashFunction = msrcryptoHashFunctions[hashName.toUpperCase()](), 26 | alg = p.algorithm; 27 | 28 | var otherInfo = 29 | utils.toArray(alg.algorithmId).concat( 30 | utils.toArray(alg.partyUInfo), 31 | utils.toArray(alg.partyVInfo), 32 | utils.toArray(alg.publicInfo) || [], 33 | utils.toArray(alg.privateInfo) || []); 34 | 35 | var reps = Math.ceil(p.length / hashFunction.hashLen), 36 | counter = 1, 37 | digest = p.keyData.concat(otherInfo), 38 | output = []; 39 | 40 | for (var i = 0; i < reps; i++) { 41 | var data = utils.int32ToBytes(counter++).concat(digest); 42 | var /*type(Array)*/ h = hashFunction.computeHash(data); 43 | output = output.concat(h); 44 | } 45 | 46 | return output.slice(0, p.length / 8); 47 | 48 | } 49 | 50 | return { 51 | deriveBits: deriveBits 52 | }; 53 | 54 | }()); 55 | 56 | var msrcryptoConcatKdfInstance = null; 57 | 58 | if (typeof operations !== "undefined") { 59 | 60 | msrcryptoConcatKdf.importKey = function (p) { 61 | var keyData; 62 | 63 | if (p.format === "raw") { 64 | keyData = msrcryptoUtilities.toArray(p.keyData); 65 | } else { 66 | throw new Error("unsupported import format"); 67 | } 68 | 69 | if (p.extractable !== false) { 70 | throw new Error("only extractable=false is supported."); 71 | } 72 | 73 | return { 74 | type: "keyImport", 75 | keyData: keyData, 76 | keyHandle: { 77 | algorithm: { name: "CONCAT" }, 78 | extractable: false, 79 | usages: p.usages, 80 | type: "secret" 81 | } 82 | }; 83 | 84 | }; 85 | 86 | operations.register("deriveBits", "CONCAT", msrcryptoConcatKdf.deriveBits); 87 | operations.register("importKey", "CONCAT", msrcryptoConcatKdf.importKey); 88 | } 89 | -------------------------------------------------------------------------------- /scripts/curves_BN.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: max-line-length 20 | 21 | // tslint:disable-next-line: variable-name 22 | var curve_BN254 = { 23 | name: "BN-254", 24 | type: 0, // Curve Type 0 = Weierstrass, 1 Twisted Edwards 25 | p: [0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xBA, 0x34, 0x4D, 0x80, 0x00, 0x00, 0x00, 0x08, 0x61, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13], 26 | a: [0x00], 27 | b: [0x02], 28 | order: [0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xBA, 0x34, 0x4D, 0x80, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x9F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x10, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D], 29 | gx: [0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xBA, 0x34, 0x4D, 0x80, 0x00, 0x00, 0x00, 0x08, 0x61, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12], 30 | gy: [0x01], 31 | cf: 1 // co-factor 32 | }; 33 | 34 | if (typeof cryptoECC !== "undefined") { 35 | // Add curves to ECC object 36 | cryptoECC.curves["BN-254"] = curve_BN254; 37 | } 38 | -------------------------------------------------------------------------------- /scripts/curves_NIST.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: max-line-length 20 | // tslint:disable: variable-name 21 | 22 | var curve_P256 = { 23 | name: "P-256", 24 | type: 0, // Curve Type 0 = Weierstrass, 1 Twisted Edwards 25 | p: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], 26 | a: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC], 27 | b: [0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B], 28 | order: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51], 29 | gx: [0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96], 30 | gy: [0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5], 31 | cf: 1 // co-factor 32 | }; 33 | 34 | var curve_P384 = { 35 | name: "P-384", 36 | type: 0, // Curve Type 0 = Weierstrass, 1 Twisted Edwards 37 | p: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF], 38 | a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC], 39 | b: [0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF], 40 | order: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73], 41 | gx: [0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7], 42 | gy: [0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F], 43 | cf: 1 // co-factor 44 | }; 45 | 46 | var curve_P521 = { 47 | name: "P-521", 48 | type: 0, // Curve Type 0 = Weierstrass, 1 Twisted Edwards 49 | p: [0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], 50 | a: [0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC], 51 | b: [0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00], 52 | order: [0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09], 53 | gx: [0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66], 54 | gy: [0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50], 55 | cf: 1 // co-factor 56 | }; 57 | 58 | if (typeof cryptoECC !== "undefined") { 59 | // Add curves to ECC object 60 | cryptoECC.curves["P-256"] = curve_P256; 61 | cryptoECC.curves["P-384"] = curve_P384; 62 | cryptoECC.curves["P-521"] = curve_P521; 63 | } 64 | -------------------------------------------------------------------------------- /scripts/curves_NUMS_old.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: max-line-length 20 | // tslint:disable: variable-name 21 | 22 | // 23 | // "Jac256": Weierstrass curve a=-3, E: gy:^2 = x^3 - 3x + 152961, p = 2^256-189 24 | // 25 | var curve_Jac256 = { 26 | // Curve ID, 2 x targeted security: level, order bitlength, prime bitlength 27 | info: ["Jac256", 256, 256, 256], 28 | // Name 29 | name: "Jac256", 30 | // Curve Type 0 = Weierstrass, 1 Twisted Edwards 31 | type: 0, 32 | // Prime p = 2^256-189 33 | p: [0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 34 | // Parameter "a" 35 | a: [0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 36 | // Parameter "b" 37 | b: [0x81, 0x55, 0x02].reverse(), 38 | // Order of the group 39 | order: [0x25, 0xa8, 0x51, 0x47, 0x29, 0x20, 0xab, 0x20, 0x60, 0x5c, 0x26, 0xea, 0x75, 0x82, 0x3c, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 40 | // x(generator) 41 | gx: [1], //, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 42 | // gy:(generator) 43 | gy: [0x77, 0x6c, 0xb5, 0xc2, 0x06, 0x63, 0xf4, 0x0b, 0xc1, 0x4e, 0x89, 0x75, 0x93, 0x2f, 0x2c, 0xd0, 0x6b, 0xdd, 0xee, 0xce, 0x6c, 0xc9, 0x82, 0xfc, 0xd7, 0x66, 0xe4, 0xc1, 0x53, 0x18, 0x6f, 0x69].reverse(), 44 | // co-factor 45 | cf: 1 46 | }; 47 | 48 | // 49 | // "Ted256": twisted Edwards curve a=-1, E: -x^2 + gy:^2 = 1 + 15342x^2gy:^2, p = 2^256-189 50 | // 51 | var curve_Ted256 = { 52 | // Curve ID, 2 x targeted security: level, order bitlength, prime bitlength 53 | info: ["Ted256", 256, 254, 256], 54 | // Name 55 | name: "Ted256", 56 | // Curve Type 0 = Weierstrass, 1 Twisted Edwards 57 | type: 1, 58 | // Prime p = 2^256-189 59 | p: [0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 60 | // Parameter "a" 61 | a: [0x42, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 62 | // Parameter "d" 63 | d: [0xEE, 0x3B].reverse(), 64 | // Order of the subgroup 65 | order: [0xad, 0xb4, 0x22, 0x11, 0x6f, 0x4e, 0xb8, 0xe5, 0x64, 0xbc, 0xa6, 0xd0, 0x5a, 0xa5, 0x6a, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f].reverse(), 66 | // gx:(generator) 67 | gx: [0x0D], 68 | // gy:(generator) 69 | gy: [0xba, 0xad, 0x1c, 0x33, 0xb5, 0x6f, 0x7f, 0x70, 0x3f, 0x30, 0x4d, 0x82, 0x63, 0x6d, 0x2a, 0xbe, 0xbf, 0x46, 0xa0, 0x9f, 0xb3, 0x30, 0xd3, 0xa3, 0xdb, 0x76, 0x12, 0x2a, 0x1e, 0xb4, 0x0a, 0x7d].reverse(), 70 | // co-factor 71 | cf: 4 72 | }; 73 | 74 | // 75 | // "Jac384": Weierstrass curve a=-3, E: gy:^2 = x^3 - 3x - 34568, p = 2^384-317 76 | // 77 | var curve_Jac384 = { 78 | // Curve ID, 2 x targeted security: level, order bitlength, prime bitlength 79 | info: ["Jac384", 384, 384, 384], 80 | // Name 81 | name: "Jac384", 82 | // Curve Type 0 = Weierstrass, 1 Twisted Edwards 83 | type: 0, 84 | // Prime p = 2^384-317 85 | p: [0xC3, 0xFE, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 86 | // Parameter "a" 87 | a: [0xC0, 0xFE, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 88 | // Parameter "b" 89 | b: [0xBB, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 90 | // Order of the group 91 | order: [0xb9, 0x61, 0x0e, 0x7b, 0xf6, 0x81, 0x4d, 0x60, 0x7a, 0xe2, 0x37, 0x4c, 0x3d, 0x9d, 0xda, 0xbe, 0x81, 0x68, 0x5d, 0xeb, 0x1e, 0xaf, 0x1e, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 92 | // x(generator) 93 | gx: [0x02], 94 | // gy:(generator) 95 | gy: [0x43, 0x6f, 0xa6, 0x3e, 0x50, 0xbf, 0xcb, 0x5b, 0x86, 0x0f, 0xd3, 0xd5, 0xba, 0xd0, 0xa3, 0xb4, 0xa2, 0xff, 0x15, 0x8d, 0xc5, 0x0d, 0x33, 0x73, 0x26, 0xf8, 0x04, 0x2f, 0x42, 0xed, 0x34, 0x80, 0xbd, 0x5d, 0x3e, 0x66, 0xe0, 0x63, 0xe7, 0x71, 0xdc, 0xb4, 0x87, 0x4b, 0xcb, 0x82, 0x9f, 0x3c].reverse(), 96 | // co-factor 97 | cf: 1 98 | }; 99 | 100 | // 101 | // "Ted384": twisted Edwards curve a=-1, E: -x^2 + gy:^2 = 1 + 333194x^2gy:^2, p = 2^384-317 102 | // 103 | var curve_Ted384 = { 104 | // Curve ID, 2 x targeted security: level, order bitlength, prime bitlength 105 | info: ["Ted384", 384, 382, 384], 106 | // Name 107 | name: "Ted384", 108 | // Curve Type 0 = Weierstrass, 1 Twisted Edwards 109 | type: 1, 110 | // Prime p = 2^2^384-317 111 | p: [0xC3, 0xFE, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 112 | // Parameter "a" 113 | a: [0xC2, 0xFE, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff].reverse(), 114 | // Parameter "d" 115 | d: [0x8A, 0x15, 0x05].reverse(), 116 | // Order of the subgroup 117 | order: [0x25, 0x6e, 0x42, 0x70, 0x1f, 0xd7, 0xd6, 0x51, 0xe4, 0xf4, 0x39, 0x8e, 0x45, 0xa0, 0x13, 0x5a, 0xa2, 0x59, 0xa2, 0xd5, 0x1e, 0xd1, 0xd7, 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f].reverse(), 118 | // x(generator) 119 | gx: [0x08], 120 | // gy:(generator) 121 | gy: [0xee, 0x5b, 0x7f, 0xfa, 0xf5, 0xac, 0xa4, 0x34, 0xd5, 0xba, 0xba, 0xfe, 0x60, 0x38, 0x00, 0x2f, 0xd7, 0xc6, 0x53, 0xe7, 0x8a, 0x8a, 0x79, 0xbd, 0x8e, 0xff, 0x0b, 0x93, 0x4c, 0x7b, 0x5c, 0xaa, 0x9d, 0x61, 0xaa, 0x94, 0x17, 0x47, 0xd4, 0x5b, 0xb6, 0xe9, 0x6c, 0x13, 0xba, 0xda, 0x9c, 0x74].reverse(), 122 | // co-factor 123 | cf: 4 124 | }; 125 | 126 | if (typeof cryptoECC !== "undefined") { 127 | // Add curves to ECC object 128 | cryptoECC.curves["TED-256"] = curve_Ted256; 129 | cryptoECC.curves["TED-384"] = curve_Ted384; 130 | cryptoECC.curves["JAC-256"] = curve_Jac256; 131 | cryptoECC.curves["JAC-384"] = curve_Jac384; 132 | } 133 | -------------------------------------------------------------------------------- /scripts/global.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | /// Store the URL for this script. We will need this later to instantiate 19 | /// new web workers (if supported). 20 | var scriptUrl = (function() { 21 | 22 | if (typeof document !== "undefined") { 23 | // Use error.stack to find out the name of this script 24 | try { 25 | throw new Error(); 26 | } catch (e) { 27 | if (e.stack) { 28 | var match = /\w+:\/\/(.+?\/)*.+\.js/.exec(e.stack); 29 | return (match && match.length > 0) ? match[0] : null; 30 | } 31 | } 32 | } else if (typeof self !== "undefined" && typeof self.location !== "undefined") { 33 | // If this script is being run in a WebWorker, 'document' will not exist 34 | // but we can use self. 35 | return self.location.href; 36 | } 37 | 38 | // We must be running in an environment without document or self. 39 | return null; 40 | 41 | /* jshint +W117 */ 42 | 43 | })(); 44 | 45 | // Indication if the user provided entropy into the entropy pool. 46 | var fprngEntropyProvided = false; 47 | 48 | // Support for webWorkers IE10+. 49 | var webWorkerSupport = (typeof Worker !== "undefined"); 50 | 51 | // Is this script running in an instance of a webWorker? 52 | var runningInWorkerInstance = typeof importScripts === "function" && self instanceof WorkerGlobalScope; 53 | 54 | // Has this worker instance been initialized 55 | var workerInitialized = false; 56 | 57 | // Typed Arrays support? 58 | var typedArraySupport = (typeof ArrayBuffer !== "undefined"); 59 | 60 | // Property setter/getter support IE9+. 61 | var setterSupport = (function() { 62 | try { 63 | Object.defineProperty({}, "oncomplete", {}); 64 | return true; 65 | } catch (ex) { 66 | return false; 67 | } 68 | }()); 69 | 70 | // We default to false in ver 1.5+ This was giving too many people problems as true by default. 71 | // We'll run in async mode if webWorkers are supported, working, and the user enables them. 72 | var asyncMode = false; 73 | 74 | var createProperty = function(parentObject, propertyName, /*@dynamic*/initialValue, getterFunction, setterFunction) { 75 | /// 76 | /// 77 | /// 78 | /// 79 | /// 80 | 81 | if (!setterSupport) { 82 | parentObject[propertyName] = initialValue; 83 | return; 84 | } 85 | 86 | var setGet = {}; 87 | 88 | // tslint:disable-next-line: no-unused-expression 89 | getterFunction && (setGet.get = getterFunction); 90 | // tslint:disable-next-line: no-unused-expression 91 | setterFunction && (setGet.set = setterFunction); 92 | 93 | Object.defineProperty( 94 | parentObject, 95 | propertyName, setGet); 96 | }; 97 | 98 | // Collection of hash functions for global availability. 99 | // Each hash function will add itself to the collection as it is evaluated. 100 | var msrcryptoHashFunctions = {}; 101 | -------------------------------------------------------------------------------- /scripts/hkdf-ctr.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | 20 | /// key derivation function from SP800-108 https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf 21 | var msrcryptoHkdfCtr = (function () { 22 | 23 | function deriveBits(p) { 24 | 25 | var algorithm = p.algorithm, 26 | keyBytes = p.keyData, 27 | bits = p.length, 28 | labelBytes = algorithm.label, 29 | contextBytes = algorithm.context, 30 | byteLen = Math.ceil(bits / 8), 31 | hLen, 32 | output = [], 33 | i, 34 | hmacContext; 35 | 36 | switch (algorithm.hash.name.toUpperCase()) { 37 | case "SHA-1": hLen = 20; break; 38 | case "SHA-256": hLen = 32; break; 39 | case "SHA-384": hLen = 48; break; 40 | case "SHA-512": hLen = 64; break; 41 | default: throw new Error("Unsupported hash algorithm."); 42 | } 43 | 44 | if (algorithm.label == null) { 45 | throw new Error("HkdfCtrParams: label: Missing required property."); 46 | } 47 | 48 | if (algorithm.context == null) { 49 | throw new Error("HkdfCtrParams: context: Missing required property."); 50 | } 51 | 52 | if (bits % 8 !== 0) { 53 | throw new Error("The length provided for HKDF-CTR is not a multiple of 8 bits."); 54 | } 55 | 56 | if (byteLen > 255 * hLen) { 57 | throw new Error("The length provided for HKDF-CTR is too large."); 58 | } 59 | 60 | // if (labelBytes.length === 0) { 61 | // labelBytes = msrcryptoUtilities.getVector(hLen); 62 | // } 63 | 64 | hmacContext = { 65 | workerid: 0, 66 | keyHandle: { algorithm: algorithm }, 67 | keyData: keyBytes, 68 | buffer: keyBytes 69 | }; 70 | 71 | // Label || 0x00 || Context || [L]2 72 | var fixed = labelBytes.concat([0],contextBytes,utils.int32ToBytes(bits)); 73 | 74 | for (i = 1; i <= Math.ceil(byteLen / hLen); i++) { 75 | hmacContext.buffer = utils.int32ToBytes(i).concat(fixed); 76 | output = output.concat(msrcryptoHmac.signHmac(hmacContext)); 77 | } 78 | 79 | return output.slice(0, byteLen); 80 | } 81 | 82 | return { 83 | deriveBits: deriveBits 84 | }; 85 | 86 | }()); 87 | 88 | if (typeof operations !== "undefined") { 89 | 90 | msrcryptoHkdfCtr.importKey = function (p) { 91 | var keyData; 92 | 93 | if (p.format === "raw") { 94 | keyData = msrcryptoUtilities.toArray(p.keyData); 95 | } else { 96 | throw new Error("unsupported import format"); 97 | } 98 | 99 | if (p.extractable !== false) { 100 | throw new Error("only extractable=false is supported."); 101 | } 102 | 103 | return { 104 | type: "keyImport", 105 | keyData: keyData, 106 | keyHandle: { 107 | algorithm: { name: "HKDF-CTR" }, 108 | extractable: false, 109 | usages: p.usages, 110 | type: "secret" 111 | } 112 | }; 113 | 114 | }; 115 | 116 | operations.register("deriveBits", "HKDF-CTR", msrcryptoHkdfCtr.deriveBits); 117 | operations.register("importKey", "HKDF-CTR", msrcryptoHkdfCtr.importKey); 118 | } 119 | -------------------------------------------------------------------------------- /scripts/hkdf.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | /// key derivation function from RFC 5869A https://www.ietf.org/rfc/rfc5869.txt 20 | var msrcryptoHkdf = (function() { 21 | 22 | function deriveBits(p) { 23 | 24 | var algorithm = p.algorithm, 25 | keyBytes = p.keyData, 26 | bits = p.length, 27 | saltBytes = algorithm.salt, 28 | byteLen = Math.ceil(bits / 8), 29 | hLen, 30 | output = [], 31 | infoBytes = msrcryptoUtilities.toArray(algorithm.info), 32 | t = [], 33 | i, 34 | hmacContext; 35 | 36 | switch (algorithm.hash.name.toUpperCase()) { 37 | case "SHA-1": hLen = 20; break; 38 | case "SHA-256": hLen = 32; break; 39 | case "SHA-384": hLen = 48; break; 40 | case "SHA-512": hLen = 64; break; 41 | default: throw new Error("Unsupported hash algorithm."); 42 | } 43 | 44 | if (algorithm.salt == null) { 45 | throw new Error("HkdfParams: salt: Missing required property."); 46 | } 47 | 48 | if (algorithm.info == null) { 49 | throw new Error("HkdfParams: info: Missing required property."); 50 | } 51 | 52 | if (bits % 8 !== 0) { 53 | throw new Error("The length provided for HKDF is not a multiple of 8 bits."); 54 | } 55 | 56 | if (byteLen > 255 * hLen) { 57 | throw new Error("The length provided for HKDF is too large."); 58 | } 59 | 60 | if (saltBytes.length === 0) { 61 | saltBytes = msrcryptoUtilities.getVector(hLen); 62 | } 63 | 64 | hmacContext = { 65 | workerid: 0, 66 | keyHandle: { algorithm: algorithm }, 67 | keyData: saltBytes, 68 | buffer: keyBytes 69 | }; 70 | 71 | hmacContext.keyData = msrcryptoHmac.signHmac(hmacContext); 72 | 73 | for (i = 0; i < Math.ceil(byteLen / hLen); i++) { 74 | hmacContext.buffer = t.concat(infoBytes).concat([1 + i]); 75 | t = msrcryptoHmac.signHmac(hmacContext); 76 | output = output.concat(t); 77 | } 78 | 79 | return output.slice(0, byteLen); 80 | } 81 | 82 | return { 83 | 84 | deriveBits: deriveBits 85 | 86 | }; 87 | 88 | }()); 89 | 90 | var msrcryptoKdfInstance = null; 91 | 92 | if (typeof operations !== "undefined") { 93 | 94 | msrcryptoHkdf.importKey = function(p) { 95 | var keyData; 96 | 97 | if (p.format === "raw") { 98 | keyData = msrcryptoUtilities.toArray(p.keyData); 99 | } else { 100 | throw new Error("unsupported import format"); 101 | } 102 | 103 | if (p.extractable !== false) { 104 | throw new Error("only extractable=false is supported."); 105 | } 106 | 107 | return { 108 | type: "keyImport", 109 | keyData: keyData, 110 | keyHandle: { 111 | algorithm: { name: "HKDF" }, 112 | extractable: false, 113 | usages: p.usages, 114 | type: "secret" 115 | } 116 | }; 117 | 118 | }; 119 | 120 | operations.register("deriveBits", "HKDF", msrcryptoHkdf.deriveBits); 121 | operations.register("importKey", "HKDF", msrcryptoHkdf.importKey); 122 | } 123 | -------------------------------------------------------------------------------- /scripts/jwk.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var msrcryptoJwk = (function() { 20 | 21 | var utils = msrcryptoUtilities; 22 | 23 | function stringToArray(stringData) { 24 | 25 | var result = []; 26 | 27 | for (var i = 0; i < stringData.length; i++) { 28 | result[i] = stringData.charCodeAt(i); 29 | } 30 | 31 | if (result[result.length - 1] === 0) { 32 | result.pop(); 33 | } 34 | 35 | return result; 36 | } 37 | 38 | function getKeyType(keyHandle) { 39 | 40 | var algType = keyHandle.algorithm.name.slice(0, 3).toUpperCase(); 41 | 42 | if (algType === "RSA") { 43 | return "RSA"; 44 | } 45 | 46 | if (algType === "ECD") { 47 | return "EC"; 48 | } 49 | 50 | return "oct"; 51 | } 52 | 53 | function hashSize(algorithm) { 54 | return algorithm.hash.name.substring(algorithm.hash.name.indexOf("-") + 1); 55 | } 56 | 57 | var algorithmMap = { 58 | 59 | "HMAC": function(algorithm) { 60 | return "HS" + hashSize(algorithm); 61 | }, 62 | 63 | "AES-CBC": function(algorithm) { 64 | return "A" + algorithm.length.toString() + "CBC"; 65 | }, 66 | 67 | "AES-GCM": function(algorithm) { 68 | return "A" + algorithm.length.toString() + "GCM"; 69 | }, 70 | 71 | "AES-KW": function(algorithm) { 72 | return "A" + algorithm.length.toString() + "KW"; 73 | }, 74 | 75 | "RSAES-PKCS1-V1_5": function(algorithm) { 76 | return "RSA1_5"; 77 | }, 78 | 79 | "RSASSA-PKCS1-V1_5": function(algorithm) { 80 | return "RS" + hashSize(algorithm); 81 | }, 82 | 83 | "RSA-OAEP": function(algorithm) { 84 | if (algorithm.hash.name.toUpperCase() === "SHA-1") { return "RSA-OAEP"; } 85 | return "RSA-OAEP-" + hashSize(algorithm); 86 | }, 87 | 88 | "RSA-PSS": function(algorithm) { 89 | return "PS" + hashSize(algorithm); 90 | }, 91 | 92 | "ECDSA": function(algorithm) { 93 | return "EC-" + algorithm.namedCurve.substring(algorithm.namedCurve.indexOf("-") + 1); 94 | } 95 | }; 96 | 97 | function keyToJwk(keyHandle, keyData) { 98 | 99 | var key = {}; 100 | 101 | key.kty = getKeyType(keyHandle); 102 | key.ext = keyHandle.extractable; 103 | if ( algorithmMap[keyHandle.algorithm.name.toUpperCase()] ) { 104 | key.alg = algorithmMap[keyHandle.algorithm.name.toUpperCase()]( keyHandle.algorithm ); 105 | } 106 | key.key_ops = keyHandle.usages; 107 | //key.key_ops = (keyHandle.type !== "secret") ? getPublicPrivateUsage(key, keyData) : keyHandle.usages; 108 | 109 | // Using .pop to determine if a property value is an array. 110 | if (keyData.pop) { 111 | key.k = utils.toBase64(keyData, true); 112 | } else { 113 | // Convert the base64Url properties to byte arrays except for key_ops 114 | for (var property in keyData) { 115 | if (keyData[property].pop && property !== "key_ops") { 116 | key[property] = utils.toBase64(keyData[property], true); 117 | } 118 | } 119 | } 120 | 121 | if (keyHandle.algorithm.namedCurve) { 122 | key.crv = keyHandle.algorithm.namedCurve; 123 | } 124 | 125 | return key; 126 | } 127 | 128 | function findUsage(usage, usages) { 129 | for (var i = 0; i < usages.length; i++) { 130 | if (usage.toUpperCase() === usages[i].toUpperCase()) { return true; } 131 | } 132 | return false; 133 | } 134 | 135 | // function getPublicPrivateUsage(keyObj, keyData) { 136 | 137 | // var newUsages = []; 138 | // var usages = keyObj.key_ops; 139 | 140 | // if (keyObj.kty.toUpperCase() === "RSA") { 141 | 142 | // if (keyData.d) { 143 | // findUsage("decrypt", usages) && newUsages.push("decrypt"); 144 | // findUsage("sign", usages) && newUsages.push("sign"); 145 | // } else { 146 | // findUsage("encrypt", usages) && newUsages.push("encrypt"); 147 | // findUsage("verify", usages) && newUsages.push("verify"); 148 | // } 149 | // return newUsages; 150 | // } 151 | 152 | // if ( keyObj.kty.toUpperCase() === "EC" ) { 153 | 154 | // if ( keyData.d ) { 155 | // findUsage( "deriveBits", usages ) && newUsages.push( "deriveBits" ); 156 | // findUsage( "deriveKey", usages ) && newUsages.push( "deriveKey" ); 157 | // } 158 | // return newUsages; 159 | // } 160 | 161 | // return keyData.usages; 162 | // } 163 | 164 | function keyToJwkOld(keyHandle, keyData) { 165 | 166 | var key = {}; 167 | 168 | key.kty = getKeyType(keyHandle); 169 | key.extractable = keyHandle.extractable; 170 | 171 | // Using .pop to determine if a property value is an array. 172 | if (keyData.pop) { 173 | key.k = utils.toBase64(keyData, true); 174 | } else { 175 | // Convert the base64Url properties to byte arrays 176 | for (var property in keyData) { 177 | if (keyData[property].pop) { 178 | key[property] = utils.toBase64(keyData[property], true); 179 | } 180 | } 181 | } 182 | 183 | if (keyHandle.algorithm.namedCurve) { 184 | key.crv = keyHandle.algorithm.namedCurve; 185 | } 186 | 187 | var stringData = JSON.stringify(key, null, "\t"); 188 | 189 | return stringToArray(stringData); 190 | } 191 | 192 | // 'jwkKeyData' is an array of bytes. Each byte is a charCode for a json key string 193 | function jwkToKey(keyData, algorithm, propsToArray) { 194 | // Convert the json string to an object 195 | var jsonKeyObject = JSON.parse(JSON.stringify(keyData)); //JSON.parse(jsonString); 196 | 197 | // Convert the base64url encoded properties to byte arrays 198 | for (var i = 0; i < propsToArray.length; i += 1) { 199 | var propValue = jsonKeyObject[propsToArray[i]]; 200 | if (propValue) { 201 | jsonKeyObject[propsToArray[i]] = 202 | utils.fromBase64(propValue); 203 | } 204 | } 205 | 206 | return jsonKeyObject; 207 | } 208 | 209 | return { 210 | keyToJwkOld: keyToJwkOld, 211 | keyToJwk: keyToJwk, 212 | jwkToKey: jwkToKey 213 | }; 214 | })(); 215 | -------------------------------------------------------------------------------- /scripts/kdf.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | /// The "concat" key derivation function from NIST SP-800-56A. 20 | var msrcryptoKdf = function(hashFunction) { 21 | 22 | var utils = msrcryptoUtilities; 23 | 24 | function deriveKey(secretBytes, otherInfo, keyOutputLength) { 25 | /// 26 | /// 27 | /// 28 | /// 29 | /// 30 | 31 | var reps = Math.ceil(keyOutputLength / (hashFunction.hashLen / 8)), 32 | counter = 1, 33 | digest = secretBytes.concat(otherInfo), 34 | output = []; 35 | 36 | for (var i = 0; i < reps; i++) { 37 | 38 | var data = utils.int32ToBytes(counter++).concat(digest); 39 | 40 | var /*type(Array)*/ h = hashFunction.computeHash(data); 41 | 42 | output = output.concat(h); 43 | } 44 | 45 | return output.slice(0, keyOutputLength); 46 | } 47 | 48 | return { 49 | 50 | deriveKey: deriveKey 51 | 52 | }; 53 | 54 | }; 55 | 56 | var msrcryptoKdfInstance = null; 57 | 58 | if (typeof operations !== "undefined") { 59 | 60 | msrcryptoKdf.deriveKey = function(/*@dynamic*/p) { 61 | 62 | var utils = msrcryptoUtilities; 63 | 64 | var hashName = p.algorithm.hash.name; 65 | 66 | var hashFunction = msrcryptoHashFunctions[hashName.toUpperCase()](); 67 | 68 | msrcryptoKdfInstance = msrcryptoKdf(hashFunction); 69 | 70 | var alg = p.algorithm; 71 | 72 | var otherInfo = 73 | utils.toArray(alg.algorithmId).concat( 74 | utils.toArray(alg.partyUInfo), 75 | utils.toArray(alg.partyVInfo), 76 | utils.toArray(alg.publicInfo), 77 | utils.toArray(alg.privateInfo)); 78 | 79 | var result = 80 | msrcryptoKdfInstance.deriveKey(p.keyData, otherInfo, p.derivedKeyType.length); 81 | 82 | msrcryptoKdfInstance = null; 83 | 84 | return { 85 | type: "keyDerive", 86 | keyData: result, 87 | keyHandle: { 88 | algorithm: p.derivedKeyType, 89 | extractable: p.extractable, 90 | usages: null || p.usages, 91 | type: "secret" 92 | } 93 | }; 94 | 95 | }; 96 | 97 | msrcryptoKdf.deriveBits = function(/*@dynamic*/p) { 98 | 99 | var hashName = p.algorithm.hash.name; 100 | 101 | var hashFunction = msrcryptoHashFunctions[hashName.toUpperCase()](); 102 | 103 | msrcryptoKdfInstance = msrcryptoKdf(hashFunction); 104 | 105 | var alg = p.algorithm; 106 | 107 | var otherInfo = 108 | alg.algorithmId.concat( 109 | alg.partyUInfo, 110 | alg.partyVInfo, 111 | alg.publicInfo || [], 112 | alg.privateInfo || []); 113 | 114 | var result = 115 | msrcryptoKdfInstance.deriveKey(p.keyData, otherInfo, p.length); 116 | 117 | msrcryptoKdfInstance = null; 118 | 119 | return result; 120 | 121 | }; 122 | 123 | operations.register("deriveKey", "concat", msrcryptoKdf.deriveKey); 124 | operations.register("deriveBits", "concat", msrcryptoKdf.deriveBits); 125 | 126 | } 127 | -------------------------------------------------------------------------------- /scripts/operations.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var operations = {}; 20 | 21 | operations.register = function(operationType, algorithmName, functionToCall) { 22 | 23 | if (!operations[operationType]) { 24 | operations[operationType] = {}; 25 | } 26 | 27 | var op = operations[operationType]; 28 | 29 | if (!op[algorithmName]) { 30 | op[algorithmName] = functionToCall; 31 | } 32 | 33 | }; 34 | 35 | operations.exists = function(operationType, algorithmName) { 36 | if (!operations[operationType]) { 37 | return false; 38 | } 39 | 40 | return operations[operationType][algorithmName] ? true : false; 41 | }; 42 | -------------------------------------------------------------------------------- /scripts/pbkdf2.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | /// The "concat" key derivation function from NIST SP-800-56A. 20 | var msrcryptoPbkdf2 = (function() { 21 | 22 | //function deriveBits(algorithm, keyBytes, bits) { 23 | function deriveBits(p) { 24 | 25 | var algorithm = p.algorithm, 26 | keyBytes = p.keyData, 27 | bits = p.length, 28 | iterations = algorithm.iterations, 29 | saltBytes = Array.apply(null, algorithm.salt), 30 | byteLen = Math.ceil(bits / 8), 31 | hLen, 32 | blockCount, 33 | output = []; 34 | 35 | switch (algorithm.hash.name.toUpperCase()) { 36 | case "SHA-1": hLen = 20; break; 37 | case "SHA-256": hLen = 32; break; 38 | case "SHA-384": hLen = 48; break; 39 | case "SHA-512": hLen = 64; break; 40 | default: throw new Error("Unsupported hash algorithm"); 41 | } 42 | 43 | // 1. If dkLen > (2 ^ 32 - 1) * hLen, output "derived key too long" 44 | 45 | // TODO: allow non-8 bit lengths 46 | blockCount = Math.ceil(byteLen / hLen); 47 | 48 | var hmacKey = msrcryptoHmac.importKey({ 49 | format: "raw", 50 | keyData: keyBytes, 51 | algorithm: { 52 | name: "HMAC", 53 | hash: algorithm.hash 54 | } 55 | }); 56 | 57 | var hmacContext = { 58 | algorithm: algorithm, 59 | keyHandle: hmacKey.keyHandle, 60 | keyData: hmacKey.keyData, 61 | workerid: 0, 62 | buffer: null 63 | }; 64 | 65 | function F(/*P,*/ S, c, i) { 66 | 67 | var result = [], 68 | // tslint:disable-next-line: no-bitwise 69 | u = S.concat([i >>> 24 & 0xFF, i >>> 16 & 0xFF, i >>> 8 & 0xFF, i & 0xFF]); 70 | 71 | for (var j = 0; j < c; j++) { 72 | hmacContext.buffer = u; 73 | u = msrcryptoHmac.signHmac(hmacContext); 74 | for (var k = 0; k < hLen; k++) { 75 | // tslint:disable-next-line: no-bitwise 76 | result[k] = ~~result[k] ^ u[k]; 77 | } 78 | } 79 | 80 | return result; 81 | } 82 | 83 | for (var block = 1; block <= blockCount; block++) { 84 | output = output.concat(F(saltBytes, iterations, block)); 85 | } 86 | 87 | output.length = byteLen; 88 | 89 | return output; 90 | } 91 | 92 | return { 93 | 94 | deriveBits: deriveBits 95 | 96 | }; 97 | 98 | }()); 99 | 100 | var msrcryptoKdfInstance = null; 101 | 102 | if (typeof operations !== "undefined") { 103 | 104 | msrcryptoPbkdf2.importKey = function(p) { 105 | var keyData; 106 | 107 | if (p.format === "raw") { 108 | keyData = msrcryptoUtilities.toArray(p.keyData); 109 | } else { 110 | throw new Error("unsupported import format"); 111 | } 112 | 113 | if (p.extractable !== false) { 114 | throw new Error("only extractable=false is supported."); 115 | } 116 | 117 | return { 118 | type: "keyImport", 119 | keyData: keyData, 120 | keyHandle: { 121 | algorithm: { name: "PBKDF2" }, 122 | extractable: false, 123 | usages: p.usages, 124 | type: "secret" 125 | } 126 | }; 127 | 128 | }; 129 | 130 | operations.register("deriveBits", "PBKDF2", msrcryptoPbkdf2.deriveBits); 131 | operations.register("importKey", "PBKDF2", msrcryptoPbkdf2.importKey); 132 | } 133 | -------------------------------------------------------------------------------- /scripts/prime.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: no-bitwise 20 | 21 | var prime = (function() { 22 | 23 | // will be populated with small primes when needed. 24 | var smallPrimes = []; 25 | 26 | // storage of trial division remainders for each small prime 27 | var trialValues = []; 28 | 29 | // for trial division generate primes up to this: 30 | var MAX_SMALL_PRIMES = 4096 * 4; 31 | 32 | function primeSieve(max) { 33 | // returns an array of primes up to a specified max. 34 | // (i.e. all primes below max - the max does not need to be prime) 35 | 36 | var numbers = new Array(max + 1), 37 | results = [], // set this to [2] if you want all the primes 38 | i, j, 39 | limit = Math.sqrt(max) | 0; 40 | 41 | for (i = 3; i <= limit; i += 2) { 42 | for (j = i * i; j <= max; j += i * 2) { 43 | numbers[j] = 0; 44 | } 45 | } 46 | 47 | for (i = 3; i <= max; i += 2) { 48 | if (numbers[i] !== 0) { 49 | results.push(i); 50 | } 51 | } 52 | 53 | return results; 54 | } 55 | 56 | function incrementalTrialDivision(increment) { 57 | // requires setupIncrementalTrialDivision() to be called first. 58 | // trialValues should be pre-populated with remainders from 59 | // initial trial divisions of all small primes into the candidate. 60 | // this will perform an increment addition and mod with each remainder 61 | // to determine if a small prime is a divisor 62 | 63 | var i, 64 | len = trialValues.length; 65 | 66 | for (i = 0; i < len; i++) { 67 | if ((trialValues[i] + increment) % smallPrimes[i] === 0) { 68 | return false; 69 | } 70 | } 71 | 72 | return true; 73 | } 74 | 75 | function setupIncrementalTrialDivision(candidate) { 76 | 77 | var i, j, r, p, y, 78 | primeCount, 79 | len = candidate.length - 1, 80 | db = cryptoMath.DIGIT_BASE, 81 | h = candidate[len]; 82 | 83 | // generate the small primes if not done already 84 | if (smallPrimes.length === 0) { smallPrimes = primeSieve(MAX_SMALL_PRIMES); } 85 | primeCount = smallPrimes.length; 86 | 87 | // trial values will contain a remainder for each small prime division 88 | trialValues = new Array(primeCount); 89 | 90 | for (i = 0; i < primeCount; i++) { 91 | 92 | j = len; 93 | y = smallPrimes[i]; 94 | 95 | if (h < y) { r = h; j--; } else { r = 0; } 96 | 97 | while (j >= 0) { 98 | p = r * db + candidate[j--]; 99 | r = p - (p / y | 0) * y; 100 | } 101 | 102 | trialValues[i] = r; 103 | } 104 | 105 | return; 106 | } 107 | 108 | // tslint:disable-next-line: variable-name 109 | function largestDivisibleByPowerOfTwo(number) { 110 | 111 | var k = 0, i = 0, s = 0, j; 112 | if (cryptoMath.isZero(number)) { return 0; } 113 | for (k = 0; number[k] === 0; k++) { /* empty */ } 114 | for (i = 0, j = 2; number[k] % j === 0; j *= 2, i++) {/* empty */ } 115 | return k * cryptoMath.DIGIT_BITS + i; 116 | } 117 | 118 | function sizeInBits(digits) { 119 | 120 | var k = 0, i = 0, j = 0; 121 | if (cryptoMath.isZero(digits)) { return 0; } 122 | for (k = digits.length - 1; digits[k] === 0; k--) {/* empty */ } 123 | for (i = cryptoMath.DIGIT_BITS - 1, j = (1 << i); i > 0; j = j >>> 1, i--) { 124 | if ((digits[k] & j) !== 0) { 125 | break; 126 | } 127 | } 128 | return k * cryptoMath.DIGIT_BITS + i; 129 | } 130 | 131 | // tslint:disable-next-line: variable-name 132 | function millerRabin(number, iterations) { 133 | 134 | var w = number; 135 | var wminus1 = []; 136 | cryptoMath.subtract(w, [1], wminus1); 137 | 138 | var a = largestDivisibleByPowerOfTwo(wminus1); 139 | 140 | var m = []; 141 | cryptoMath.shiftRight(wminus1, m, a); 142 | 143 | var wlen = sizeInBits(w); 144 | var b; 145 | var montmul = cryptoMath.MontgomeryMultiplier(w); 146 | 147 | for (var i = 1; i <= iterations; i++) { 148 | 149 | var status = false; 150 | 151 | do { 152 | b = getRandomOddNumber(wlen); 153 | } while (cryptoMath.compareDigits(b, wminus1) >= 0); 154 | 155 | var z = []; 156 | 157 | montmul.modExp(b, m, z, true); 158 | 159 | if (cryptoMath.compareDigits(z, [1]) === 0 || cryptoMath.compareDigits(z, wminus1) === 0) { continue; } 160 | 161 | for (var j = 1; j < a; j++) { 162 | 163 | montmul.montgomeryMultiply(z, z, z); 164 | 165 | if (cryptoMath.compareDigits(z, wminus1) === 0) { 166 | status = true; 167 | break; 168 | } 169 | 170 | if (cryptoMath.compareDigits(z, [1]) === 0) { 171 | return false; 172 | } 173 | } 174 | 175 | if (status === false) { return false; } 176 | } 177 | 178 | return true; 179 | } 180 | 181 | function generatePrime(bits) { 182 | 183 | var candidate = getRandomOddNumber(bits), 184 | inc = 0, 185 | possiblePrime, 186 | isPrime = false, 187 | candidatePlusInc = []; 188 | 189 | setupIncrementalTrialDivision(candidate); 190 | 191 | while (true) { 192 | 193 | possiblePrime = incrementalTrialDivision(inc); 194 | 195 | if (possiblePrime) { 196 | cryptoMath.add(candidate, [inc], candidatePlusInc); 197 | if (millerRabin(candidatePlusInc, 6) === true) { return candidatePlusInc; } 198 | } 199 | 200 | inc += 2; 201 | } 202 | 203 | } 204 | 205 | function getRandomOddNumber(bits) { 206 | 207 | var numBytes = Math.ceil(bits / 8), 208 | bytes = msrcryptoPseudoRandom.getBytes(numBytes), 209 | digits; 210 | 211 | bytes[0] |= 128; 212 | bytes[bytes.length - 1] |= 1; 213 | 214 | return cryptoMath.bytesToDigits(bytes); 215 | 216 | } 217 | 218 | return { 219 | generatePrime: generatePrime 220 | }; 221 | 222 | })(); 223 | -------------------------------------------------------------------------------- /scripts/qunit/qunit-1.23.1.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * QUnit 1.23.1 3 | * https://qunitjs.com/ 4 | * 5 | * Copyright jQuery Foundation and other contributors 6 | * Released under the MIT license 7 | * https://jquery.org/license 8 | * 9 | * Date: 2016-04-12T17:29Z 10 | */ 11 | 12 | /** Font Family and Sizes */ 13 | 14 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult { 15 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 16 | } 17 | 18 | #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 19 | #qunit-tests { font-size: smaller; } 20 | 21 | 22 | /** Resets */ 23 | 24 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { 25 | margin: 0; 26 | padding: 0; 27 | } 28 | 29 | 30 | /** Header */ 31 | 32 | #qunit-header { 33 | padding: 0.5em 0 0.5em 1em; 34 | 35 | color: #8699A4; 36 | background-color: #0D3349; 37 | 38 | font-size: 1.5em; 39 | line-height: 1em; 40 | font-weight: 400; 41 | 42 | border-radius: 5px 5px 0 0; 43 | } 44 | 45 | #qunit-header a { 46 | text-decoration: none; 47 | color: #C2CCD1; 48 | } 49 | 50 | #qunit-header a:hover, 51 | #qunit-header a:focus { 52 | color: #FFF; 53 | } 54 | 55 | #qunit-testrunner-toolbar label { 56 | display: inline-block; 57 | padding: 0 0.5em 0 0.1em; 58 | } 59 | 60 | #qunit-banner { 61 | height: 5px; 62 | } 63 | 64 | #qunit-testrunner-toolbar { 65 | padding: 0.5em 1em 0.5em 1em; 66 | color: #5E740B; 67 | background-color: #EEE; 68 | overflow: hidden; 69 | } 70 | 71 | #qunit-filteredTest { 72 | padding: 0.5em 1em 0.5em 1em; 73 | background-color: #F4FF77; 74 | color: #366097; 75 | } 76 | 77 | #qunit-userAgent { 78 | padding: 0.5em 1em 0.5em 1em; 79 | background-color: #2B81AF; 80 | color: #FFF; 81 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 82 | } 83 | 84 | #qunit-modulefilter-container { 85 | float: right; 86 | padding: 0.2em; 87 | } 88 | 89 | .qunit-url-config { 90 | display: inline-block; 91 | padding: 0.1em; 92 | } 93 | 94 | .qunit-filter { 95 | display: block; 96 | float: right; 97 | margin-left: 1em; 98 | } 99 | 100 | /** Tests: Pass/Fail */ 101 | 102 | #qunit-tests { 103 | list-style-position: inside; 104 | } 105 | 106 | #qunit-tests li { 107 | padding: 0.4em 1em 0.4em 1em; 108 | border-bottom: 1px solid #FFF; 109 | list-style-position: inside; 110 | } 111 | 112 | #qunit-tests > li { 113 | display: none; 114 | } 115 | 116 | #qunit-tests li.running, 117 | #qunit-tests li.pass, 118 | #qunit-tests li.fail, 119 | #qunit-tests li.skipped { 120 | display: list-item; 121 | } 122 | 123 | #qunit-tests.hidepass { 124 | position: relative; 125 | } 126 | 127 | #qunit-tests.hidepass li.running, 128 | #qunit-tests.hidepass li.pass { 129 | visibility: hidden; 130 | position: absolute; 131 | width: 0; 132 | height: 0; 133 | padding: 0; 134 | border: 0; 135 | margin: 0; 136 | } 137 | 138 | #qunit-tests li strong { 139 | cursor: pointer; 140 | } 141 | 142 | #qunit-tests li.skipped strong { 143 | cursor: default; 144 | } 145 | 146 | #qunit-tests li a { 147 | padding: 0.5em; 148 | color: #C2CCD1; 149 | text-decoration: none; 150 | } 151 | 152 | #qunit-tests li p a { 153 | padding: 0.25em; 154 | color: #6B6464; 155 | } 156 | #qunit-tests li a:hover, 157 | #qunit-tests li a:focus { 158 | color: #000; 159 | } 160 | 161 | #qunit-tests li .runtime { 162 | float: right; 163 | font-size: smaller; 164 | } 165 | 166 | .qunit-assert-list { 167 | margin-top: 0.5em; 168 | padding: 0.5em; 169 | 170 | background-color: #FFF; 171 | 172 | border-radius: 5px; 173 | } 174 | 175 | .qunit-source { 176 | margin: 0.6em 0 0.3em; 177 | } 178 | 179 | .qunit-collapsed { 180 | display: none; 181 | } 182 | 183 | #qunit-tests table { 184 | border-collapse: collapse; 185 | margin-top: 0.2em; 186 | } 187 | 188 | #qunit-tests th { 189 | text-align: right; 190 | vertical-align: top; 191 | padding: 0 0.5em 0 0; 192 | } 193 | 194 | #qunit-tests td { 195 | vertical-align: top; 196 | } 197 | 198 | #qunit-tests pre { 199 | margin: 0; 200 | white-space: pre-wrap; 201 | word-wrap: break-word; 202 | } 203 | 204 | #qunit-tests del { 205 | background-color: #E0F2BE; 206 | color: #374E0C; 207 | text-decoration: none; 208 | } 209 | 210 | #qunit-tests ins { 211 | background-color: #FFCACA; 212 | color: #500; 213 | text-decoration: none; 214 | } 215 | 216 | /*** Test Counts */ 217 | 218 | #qunit-tests b.counts { color: #000; } 219 | #qunit-tests b.passed { color: #5E740B; } 220 | #qunit-tests b.failed { color: #710909; } 221 | 222 | #qunit-tests li li { 223 | padding: 5px; 224 | background-color: #FFF; 225 | border-bottom: none; 226 | list-style-position: inside; 227 | } 228 | 229 | /*** Passing Styles */ 230 | 231 | #qunit-tests li li.pass { 232 | color: #3C510C; 233 | background-color: #FFF; 234 | border-left: 10px solid #C6E746; 235 | } 236 | 237 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 238 | #qunit-tests .pass .test-name { color: #366097; } 239 | 240 | #qunit-tests .pass .test-actual, 241 | #qunit-tests .pass .test-expected { color: #999; } 242 | 243 | #qunit-banner.qunit-pass { background-color: #C6E746; } 244 | 245 | /*** Failing Styles */ 246 | 247 | #qunit-tests li li.fail { 248 | color: #710909; 249 | background-color: #FFF; 250 | border-left: 10px solid #EE5757; 251 | white-space: pre; 252 | } 253 | 254 | #qunit-tests > li:last-child { 255 | border-radius: 0 0 5px 5px; 256 | } 257 | 258 | #qunit-tests .fail { color: #000; background-color: #EE5757; } 259 | #qunit-tests .fail .test-name, 260 | #qunit-tests .fail .module-name { color: #000; } 261 | 262 | #qunit-tests .fail .test-actual { color: #EE5757; } 263 | #qunit-tests .fail .test-expected { color: #008000; } 264 | 265 | #qunit-banner.qunit-fail { background-color: #EE5757; } 266 | 267 | /*** Skipped tests */ 268 | 269 | #qunit-tests .skipped { 270 | background-color: #EBECE9; 271 | } 272 | 273 | #qunit-tests .qunit-skipped-label { 274 | background-color: #F4FF77; 275 | display: inline-block; 276 | font-style: normal; 277 | color: #366097; 278 | line-height: 1.8em; 279 | padding: 0 0.5em; 280 | margin: -0.4em 0.4em -0.4em 0; 281 | } 282 | 283 | /** Result */ 284 | 285 | #qunit-testresult { 286 | padding: 0.5em 1em 0.5em 1em; 287 | 288 | color: #2B81AF; 289 | background-color: #D2E0E6; 290 | 291 | border-bottom: 1px solid #FFF; 292 | } 293 | #qunit-testresult .module-name { 294 | font-weight: 700; 295 | } 296 | 297 | /** Fixture */ 298 | 299 | #qunit-fixture { 300 | position: absolute; 301 | top: -10000px; 302 | left: -10000px; 303 | width: 1000px; 304 | height: 1000px; 305 | } -------------------------------------------------------------------------------- /scripts/rsa-base.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var msrcryptoRsaBase = function(keyStruct) { 20 | 21 | var utils = msrcryptoUtilities, 22 | keyIsPrivate = keyStruct.hasOwnProperty("n") && keyStruct.hasOwnProperty("d"), 23 | keyIsCrt = keyStruct.hasOwnProperty("p") && keyStruct.hasOwnProperty("q"), 24 | modulusLength = keyStruct.n.length; 25 | 26 | function toBytes(digits) { 27 | 28 | var bytes = cryptoMath.digitsToBytes(digits); 29 | 30 | // Add leading zeros until the message is the proper length. 31 | utils.padFront(bytes, 0, modulusLength); 32 | 33 | return bytes; 34 | } 35 | 36 | function modExp(dataBytes, expBytes, modulusBytes) { 37 | /// Result in a digit array. 38 | var exponent = cryptoMath.bytesToDigits(expBytes); 39 | 40 | var group = cryptoMath.IntegerGroup(modulusBytes); 41 | var base = group.createElementFromBytes(dataBytes); 42 | var result = group.modexp(base, exponent); 43 | 44 | // var modulus = cryptoMath.bytesToDigits(modulusBytes); 45 | // var exponent = cryptoMath.bytesToDigits(expBytes); 46 | // var base = cryptoMath.bytesToDigits(dataBytes); 47 | 48 | // var result = cryptoMath.modExp(base, exponent, modulus); 49 | 50 | return result.m_digits; 51 | } 52 | 53 | function decryptModExp(cipherBytes) { 54 | 55 | var resultElement = modExp(cipherBytes, keyStruct.d, keyStruct.n); 56 | 57 | return toBytes(resultElement); 58 | } 59 | 60 | function decryptCrt(cipherBytes) { 61 | 62 | var b2d = cryptoMath.bytesToDigits, 63 | p = keyStruct.p, 64 | q = keyStruct.q, 65 | dp = keyStruct.dp, 66 | dq = keyStruct.dq, 67 | invQ = keyStruct.qi, 68 | pDigits = b2d(p), 69 | qDigits = b2d(q), 70 | temp = new Array(pDigits.length + qDigits.length), 71 | m1Digits = new Array(pDigits.length + 1), 72 | m2Digits = new Array(qDigits.length + 1), 73 | cDigits = b2d(cipherBytes), 74 | mm = cryptoMath.MontgomeryMultiplier, 75 | mmp = new mm(keyStruct.ctxp ? undefined : pDigits, keyStruct.ctxp), // pre-constructed montgomery multiplier 76 | mmq = new mm(keyStruct.ctxq ? undefined : qDigits, keyStruct.ctxq); 77 | 78 | // 'm1' = (c mod p)^dP mod p 79 | mmp.reduce(cDigits, temp); 80 | mmp.modExp(temp, b2d(dp), m1Digits); 81 | 82 | // 'm2' = (c mod q)^dQ mod q 83 | mmq.reduce(cDigits, temp); 84 | mmq.modExp(temp, b2d(dq), m2Digits); 85 | 86 | // 'diff' = (m1 - m2). Compute as follows to have |m1 - m2|. 87 | // m1 - m2 if m1>=m2. 88 | // m2 - m1 if m1>> 24 & 0xff, 146 | counter >>> 16 & 0xff, 147 | counter >>> 8 & 0xff, 148 | counter & 0xff 149 | ]; 150 | // tslint:enable: no-bitwise 151 | 152 | hash = hashFunction.computeHash(seedBytes.concat(bytes)); 153 | 154 | t = t.concat(hash); 155 | } 156 | 157 | return t.slice(0, maskLen); 158 | }, 159 | 160 | checkMessageVsMaxHash: function(messageBytes, hashFunction) { 161 | 162 | // The max array size in JS is 2^32-1 163 | if (messageBytes.length > (hashFunction.maxMessageSize || 0xFFFFFFFF)) { 164 | throw new Error("message too long"); 165 | } 166 | 167 | return; 168 | } 169 | 170 | }; 171 | -------------------------------------------------------------------------------- /scripts/rsa-oaep.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var rsaMode = rsaMode || {}; 20 | 21 | rsaMode.oaep = function(keyStruct, hashFunction) { 22 | 23 | var utils = msrcryptoUtilities, 24 | random = msrcryptoPseudoRandom, 25 | size = keyStruct.n.length; 26 | 27 | if (hashFunction === null) { 28 | throw new Error("must supply hashFunction"); 29 | } 30 | 31 | function pad(/*@type(Array)*/ message, /*@optional*/ label) { 32 | 33 | var lHash, psLen, psArray, i, db, seed; 34 | var dbMask, maskeddb, seedMask, maskedSeed; 35 | var /*@type(Array)*/ encodedMessage; 36 | 37 | if (message.length > (size - 2 * (hashFunction.hashLen / 8) - 2)) { 38 | throw new Error("Message too long."); 39 | } 40 | 41 | if (label == null) { label = []; } 42 | 43 | lHash = hashFunction.computeHash(/*@static_cast(Digits)*/label); 44 | 45 | psLen = size - message.length - (2 * lHash.length) - 2; 46 | psArray = utils.getVector(psLen); 47 | 48 | // 'db' = 'lHash' || 'psArray' || 0x01 || message 49 | db = lHash.concat(psArray, [1], message); 50 | 51 | seed = random.getBytes(lHash.length); 52 | 53 | dbMask = rsaShared.mgf1(seed, size - lHash.length - 1, hashFunction); 54 | 55 | maskeddb = utils.xorVectors(db, dbMask); 56 | 57 | seedMask = rsaShared.mgf1(maskeddb, lHash.length, hashFunction); 58 | 59 | maskedSeed = utils.xorVectors(seed, seedMask); 60 | 61 | encodedMessage = [0].concat(maskedSeed).concat(maskeddb); 62 | 63 | message = encodedMessage.slice(); 64 | 65 | return message; 66 | } 67 | 68 | function unpad(/*@type(Array)*/ encodedBytes, /*@optional*/ labelBytes) { 69 | 70 | var lHash, maskedSeed, maskeddb, seedMask; 71 | var seed, dbMask, db; 72 | var lHashp, i = 0; 73 | var valid = encodedBytes[0] === 0; 74 | 75 | if (!labelBytes) { 76 | labelBytes = []; 77 | } 78 | 79 | lHash = hashFunction.computeHash(labelBytes); 80 | 81 | maskedSeed = encodedBytes.slice(1, lHash.length + 1); 82 | maskeddb = encodedBytes.slice(lHash.length + 1); 83 | 84 | seedMask = rsaShared.mgf1(maskeddb, lHash.length, hashFunction); 85 | seed = utils.xorVectors(maskedSeed, seedMask); 86 | dbMask = rsaShared.mgf1(seed, size - lHash.length - 1, hashFunction); 87 | 88 | db = utils.xorVectors(maskeddb, dbMask); 89 | 90 | lHashp = db.slice(0, lHash.length); 91 | 92 | // lHashp should equal lHash or 'Encryption Error' 93 | valid = valid && utils.arraysEqual(lHash, lHashp); 94 | 95 | db = db.slice(lHash.length); 96 | 97 | // There will be a bunch of zeros followed by a 1 98 | while (!db[i++]) { /* empty */ } 99 | 100 | return { 101 | valid: valid, 102 | data: db.slice(i) 103 | }; 104 | } 105 | 106 | return { 107 | 108 | pad: function(/*@type(Array)*/ messageBytes, /*@optional*/ labelBytes) { 109 | return pad(messageBytes, labelBytes); 110 | }, 111 | 112 | unpad: function(/*@type(Array)*/ encodedBytes, /*@optional*/ labelBytes) { 113 | return unpad(encodedBytes, labelBytes); 114 | } 115 | }; 116 | 117 | }; 118 | -------------------------------------------------------------------------------- /scripts/rsa-pkcs1.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var rsaMode = rsaMode || {}; 20 | 21 | rsaMode.pkcs1Encrypt = function(keyStruct) { 22 | 23 | var random = msrcryptoPseudoRandom, 24 | size = keyStruct.n.length; 25 | 26 | function pad(data) { 27 | 28 | var randomness; 29 | 30 | if (data.length > size - 11) { 31 | throw new Error("message too long"); 32 | } 33 | 34 | // A minimum of 8 random bytes 35 | randomness = random.getNonZeroBytes(size - data.length - 3); 36 | 37 | return [0, 2].concat(randomness, [0], data); 38 | } 39 | 40 | function validatePadding(paddedData) { 41 | // Validate the padding: 42 | // we cannot know how much padding there should be. 43 | // we can know that: 44 | // a. the first two bytes should be 0,2 45 | // b. the next eight bytes are non-zero 46 | 47 | // validate first 2 bytes of padding are 0, 2 48 | var paddingValid = paddedData[0] === 0 && paddedData[1] === 2; 49 | 50 | // verify no zeros from bytes 2-10 51 | for (var i = 2; i < 10; i++) { 52 | paddingValid = paddingValid && !!paddedData[i]; 53 | } 54 | 55 | return paddingValid; 56 | } 57 | 58 | function unpad(paddedData) { 59 | 60 | var i, 61 | paddingIsValid = validatePadding(paddedData), 62 | startOfData = 0; 63 | 64 | for (i = 1; i < paddedData.length; i += 1) { 65 | // scan data for first zero byte 66 | startOfData = startOfData || +!paddedData[i] && i + 1; 67 | } 68 | 69 | startOfData = (-paddingIsValid && startOfData); 70 | 71 | return { 72 | data: paddedData.slice(startOfData), 73 | valid: paddingIsValid 74 | }; 75 | } 76 | 77 | return { 78 | 79 | pad: function(messageBytes) { 80 | return pad(messageBytes); 81 | }, 82 | 83 | unpad: function(encodedBytes) { 84 | return unpad(encodedBytes); 85 | } 86 | }; 87 | 88 | }; 89 | 90 | rsaMode.pkcs1Sign = function(keyStruct, hashFunction) { 91 | 92 | var utils = msrcryptoUtilities, 93 | size = keyStruct.n.length; 94 | 95 | function emsa_pkcs1_v15_encode(messageBytes) { 96 | 97 | var paddedData, 98 | hash, 99 | tlen; 100 | 101 | hash = hashFunction.computeHash(messageBytes.slice()); 102 | 103 | paddedData = hashFunction.der.concat(hash); 104 | 105 | tlen = paddedData.length; 106 | 107 | if (size < tlen + 11) { 108 | throw new Error("intended encoded message length too short"); 109 | } 110 | 111 | return [0x00, 0x01].concat( 112 | utils.getVector(size - tlen - 3, 0xFF), 113 | [0], 114 | paddedData); 115 | } 116 | 117 | return { 118 | 119 | sign: function(messageBytes) { 120 | return emsa_pkcs1_v15_encode(messageBytes); 121 | }, 122 | 123 | verify: function(signatureBytes, messageBytes) { 124 | var emp = emsa_pkcs1_v15_encode(messageBytes); 125 | 126 | return utils.arraysEqual(signatureBytes, emp); 127 | 128 | } 129 | }; 130 | }; 131 | -------------------------------------------------------------------------------- /scripts/rsa-pss.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: no-bitwise 20 | 21 | var rsaMode = rsaMode || {}; 22 | 23 | rsaMode.pss = function(keyStruct, hashFunction) { 24 | var utils = msrcryptoUtilities, 25 | random = msrcryptoPseudoRandom; 26 | 27 | function emsa_pss_encode(messageBytes, /*@optional*/ saltLength, /*@optional*/ salt) { 28 | var modulusBits = cryptoMath.bitLength(keyStruct.n), 29 | emBits = modulusBits - 1, 30 | emLen = Math.ceil(emBits / 8), 31 | mHash = hashFunction.computeHash(messageBytes); 32 | 33 | saltLength = salt ? salt.length : saltLength == null ? mHash.length : saltLength; 34 | 35 | if (emLen < mHash.length + saltLength + 2) { 36 | throw new Error("encoding error"); 37 | } 38 | 39 | salt = salt || random.getBytes(saltLength); 40 | 41 | // M' = (0x) 00 00 00 00 00 00 00 00 || mHash || salt 42 | var mp = [ 0, 0, 0, 0, 0, 0, 0, 0 ].concat(mHash, salt); 43 | 44 | var h = hashFunction.computeHash(mp); 45 | 46 | var ps = utils.getVector(emLen - salt.length - h.length - 2); 47 | 48 | var db = ps.concat([ 1 ], salt); 49 | 50 | var dbMask = rsaShared.mgf1(h, emLen - h.length - 1, hashFunction); 51 | 52 | var maskedDb = utils.xorVectors(db, dbMask); 53 | 54 | // Set the ((8 * emLen) - emBits) of the leftmost octect in maskedDB to zero 55 | var mask = 0; 56 | for (var i = 0; i < 8 - (8 * emLen - emBits); i++) { 57 | mask += 1 << i; 58 | } 59 | maskedDb[0] &= mask; 60 | 61 | var em = maskedDb.concat(h, [ 0xbc ]); 62 | 63 | return em; 64 | } 65 | 66 | function emsa_pss_verify(signatureBytes, messageBytes, /*@optional*/ saltLength) { 67 | var modulusBits = cryptoMath.bitLength(keyStruct.n); 68 | 69 | var emBits = modulusBits - 1; 70 | 71 | var emLen = Math.ceil(emBits / 8); 72 | 73 | var mHash = hashFunction.computeHash(messageBytes); 74 | 75 | var hLen = mHash.length; 76 | 77 | saltLength = saltLength == null ? hLen : saltLength; 78 | 79 | if (emLen < hLen + saltLength + 2) { 80 | return false; 81 | } 82 | 83 | var maskedDb = signatureBytes.slice(0, emLen - hLen - 1); 84 | 85 | var h = signatureBytes.slice(maskedDb.length, maskedDb.length + hLen); 86 | 87 | var dbMask = rsaShared.mgf1(h, emLen - hLen - 1, hashFunction); 88 | 89 | var /*@type(Array)*/ db = utils.xorVectors(maskedDb, dbMask); 90 | 91 | // Set the leftmost 8 * emLen - emBits of db[0] to zero 92 | db[0] &= 0xff >>> (8 - (8 * emLen - emBits)); 93 | 94 | // Verify the leftmost bytes are zero 95 | for (var i = 0; i < emLen - hLen - saltLength - 2; i++) { 96 | if (db[i] !== 0) { 97 | return false; 98 | } 99 | } 100 | 101 | if (db[emLen - hLen - saltLength - 2] !== 0x01) { 102 | return false; 103 | } 104 | 105 | var salt = db.slice(db.length - saltLength); 106 | 107 | // M' = (0x) 00 00 00 00 00 00 00 00 || mHash || salt 108 | var mp = [ 0, 0, 0, 0, 0, 0, 0, 0 ].concat(mHash, salt); 109 | 110 | var hp = hashFunction.computeHash(mp); 111 | 112 | return utils.arraysEqual(hp, h); 113 | } 114 | 115 | return { 116 | sign : function(messageBytes, /*@optional*/ saltLength, /*@optional*/ salt) { 117 | return emsa_pss_encode(messageBytes, saltLength, salt); 118 | }, 119 | 120 | verify : function(signatureBytes, messageBytes, /*@optional*/ saltLength) { 121 | return emsa_pss_verify(signatureBytes, messageBytes, saltLength); 122 | } 123 | }; 124 | }; 125 | -------------------------------------------------------------------------------- /scripts/sha.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var msrcryptoSha = function(name, der, h, k, blockBytes, blockFunction, truncateTo) { 20 | /// 21 | /// Returns a hash function using the passed in parameters. 22 | /// 23 | /// Name of the hash function. 24 | /// 25 | /// 26 | /// 27 | /// The number of bytes in a block. 28 | /// Function for processing blocks. 29 | /// Truncate the resulting hash to a fixed length. 30 | /// 31 | 32 | var utils = msrcryptoUtilities; 33 | 34 | // Make a copy of h so we don't alter the initialization array. 35 | var hv = h.slice(), 36 | w = new Array(blockBytes), 37 | buffer = [], 38 | blocksProcessed = 0; 39 | 40 | function hashBlocks(message) { 41 | /// 42 | /// Breaks a array of data into full blocks and hashes each block in sequence. 43 | /// Data at the end of the message that does not fill an entire block is 44 | /// returned. 45 | /// 46 | /// Byte data to hash 47 | /// Unprocessed data at the end of the message that did 48 | /// not fill an entire block. 49 | 50 | var blockCount = Math.floor(message.length / blockBytes); 51 | 52 | // Process each block of the message 53 | for (var block = 0; block < blockCount; block++) { 54 | blockFunction(message, block, hv, k, w); 55 | } 56 | 57 | // Keep track of the number of blocks processed. 58 | // We have to put the total message size into the padding. 59 | blocksProcessed += blockCount; 60 | 61 | // Return the unprocessed data. 62 | return message.slice(blockCount * blockBytes); 63 | } 64 | 65 | function hashToBytes() { 66 | /// 67 | /// Converts stored hash values (32-bit ints) to bytes. 68 | /// 69 | /// 70 | 71 | // Move the results to an uint8 array. 72 | var hash = []; 73 | 74 | for (var i = 0; i < hv.length; i++) { 75 | hash = hash.concat(utils.int32ToBytes(hv[i])); 76 | } 77 | 78 | // Truncate the results depending on the hash algorithm used. 79 | hash.length = truncateTo / 8; 80 | 81 | return hash; 82 | } 83 | 84 | function addPadding(messageBytes) { 85 | /// 86 | /// Builds and appends padding to a message 87 | /// 88 | /// Message to pad 89 | /// The message array + padding 90 | 91 | var padLen = blockBytes - messageBytes.length % blockBytes; 92 | 93 | // If there is 8 (16 for sha-512) or less bytes of padding, pad an additional block. 94 | // tslint:disable-next-line: no-unused-expression 95 | (padLen <= (blockBytes / 8)) && (padLen += blockBytes); 96 | 97 | // Create a new Array that will contain the message + padding 98 | var padding = utils.getVector(padLen); 99 | 100 | // Set the 1 bit at the end of the message data 101 | padding[0] = 128; 102 | 103 | // Set the length equal to the previous data len + the new data len 104 | var messageLenBits = (messageBytes.length + blocksProcessed * blockBytes) * 8; 105 | 106 | // Set the message length in the last 8 bytes 107 | //padding[padLen - 4] = messageLenBits >>> 24 & 255; 108 | //padding[padLen - 3] = messageLenBits >>> 16 & 255; 109 | //padding[padLen - 2] = messageLenBits >>> 8 & 255; 110 | //padding[padLen - 1] = messageLenBits & 255; 111 | //messageLenBits = Math.floor(messageLenBits / 0x100000000); 112 | //padding[padLen - 8] = messageLenBits >>> 24 & 255; 113 | //padding[padLen - 7] = messageLenBits >>> 16 & 255; 114 | //padding[padLen - 6] = messageLenBits >>> 8 & 255; 115 | //padding[padLen - 5] = messageLenBits & 255; 116 | 117 | for (var i = 1; i <= 8; i++) { 118 | padding[padLen - i] = messageLenBits % 0x100; 119 | messageLenBits = Math.floor(messageLenBits / 0x100); 120 | } 121 | return messageBytes.concat(padding); 122 | } 123 | 124 | function computeHash(messageBytes) { 125 | /// 126 | /// Computes the hash of an entire message. 127 | /// 128 | /// Byte array to hash 129 | /// Hash of message bytes 130 | 131 | buffer = hashBlocks(messageBytes); 132 | 133 | return finish(); 134 | } 135 | 136 | function process(messageBytes) { 137 | /// 138 | /// Call process repeatedly to hash a stream of bytes. Then call 'finish' to 139 | /// complete the hash and get the final result. 140 | /// 141 | /// 142 | 143 | // Append the new data to the buffer (previous unprocessed data) 144 | buffer = buffer.concat(messageBytes); 145 | 146 | // If there is at least one block of data, hash it 147 | if (buffer.length >= blockBytes) { 148 | 149 | // The remaining unprocessed data goes back into the buffer 150 | buffer = hashBlocks(buffer); 151 | } 152 | 153 | return; 154 | } 155 | 156 | function finish() { 157 | /// 158 | /// Called after one or more calls to process. This will finalize the hashing 159 | /// of the 'streamed' data and return the hash. 160 | /// 161 | /// Hash of message bytes 162 | 163 | // All the full blocks of data have been processed. Now we pad the rest and hash. 164 | // Buffer should be empty now. 165 | if (hashBlocks(addPadding(buffer)).length !== 0) { 166 | throw new Error("buffer.length !== 0"); 167 | } 168 | 169 | // Convert the intermediate hash values to bytes 170 | var result = hashToBytes(); 171 | 172 | // Reset the buffer 173 | buffer = []; 174 | 175 | // Restore the initial hash values 176 | hv = h.slice(); 177 | 178 | // Reset the block counter 179 | blocksProcessed = 0; 180 | 181 | return result; 182 | } 183 | 184 | return { 185 | name: name, 186 | computeHash: computeHash, 187 | process: process, 188 | finish: finish, 189 | der: der, 190 | hashLen: truncateTo, 191 | maxMessageSize: 0xFFFFFFFF // (2^32 - 1 is max array size in JavaScript) 192 | }; 193 | 194 | }; 195 | -------------------------------------------------------------------------------- /scripts/sha1.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: no-bitwise 20 | var msrcryptoSha1 = (function() { 21 | 22 | // tslint:disable-next-line: no-shadowed-variable 23 | function hashBlock(message, blockIndex, hv, k, w) { 24 | /// 25 | /// Block function for hashing algorithm to use. 26 | /// 27 | /// Block data to hash 28 | /// The block of the data to hash 29 | /// Initial hash values 30 | /// K constants 31 | /// Buffer for w values 32 | /// Updated initial hash values 33 | 34 | var t, i, temp, x0, blockSize = 64, mask = 0xFFFFFFFF; 35 | 36 | var ra = hv[0], 37 | rb = hv[1], 38 | rc = hv[2], 39 | rd = hv[3], 40 | re = hv[4]; 41 | 42 | // 0 ≤ t ≤ 15 43 | for (i = 0; i < 16; i++) { 44 | w[i] = utils.bytesToInt32(message, blockIndex * blockSize + i * 4); 45 | } 46 | 47 | // 16 ≤ t ≤ 79 48 | for (t = 16; t < 80; t++) { 49 | x0 = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]; 50 | w[t] = (x0 << 1) | (x0 >>> 31); 51 | } 52 | 53 | for (i = 0; i < 80; i++) { 54 | 55 | // Ch(x, y, z)=(x & y) ^ (~x & z) 56 | temp = ((ra << 5) | (ra >>> 27)); 57 | 58 | temp += 59 | i >= 60 ? (rb ^ rc ^ rd) : 60 | i >= 40 ? ((rb & rc) ^ (rb & rd) ^ (rc & rd)) : 61 | i >= 20 ? (rb ^ rc ^ rd) : 62 | /*i<=20*/ ((rb & rc) ^ ((~rb) & rd)); 63 | 64 | temp += (re + k[i] + w[i]); 65 | 66 | re = rd; 67 | rd = rc; 68 | rc = ((rb << 30) | (rb >>> 2)); 69 | rb = ra; 70 | ra = temp; 71 | } 72 | 73 | // Update the hash values 74 | hv[0] += ra & mask; 75 | hv[1] += rb & mask; 76 | hv[2] += rc & mask; 77 | hv[3] += rd & mask; 78 | hv[4] += re & mask; 79 | 80 | return hv; 81 | } 82 | 83 | var utils = msrcryptoUtilities, 84 | upd = utils.unpackData, 85 | h = upd("Z0UjAe/Nq4mYutz+EDJUdsPS4fA=", 4, 1), 86 | // tslint:disable-next-line: max-line-length 87 | k = upd("WoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroY8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdY", 4, 1), 88 | der = upd("MCEwCQYFKw4DAhoFAAQU"); 89 | 90 | return { 91 | sha1: function() { 92 | return msrcryptoSha("SHA-1", der, h, k, 64, hashBlock, 160); 93 | } 94 | }; 95 | 96 | })(); 97 | 98 | if (typeof operations !== "undefined") { 99 | 100 | msrcryptoSha1.instances = {}; 101 | 102 | msrcryptoSha1.getInstance = function(id) { 103 | return msrcryptoSha1.instances[id] || (msrcryptoSha1.instances[id] = msrcryptoSha1.sha1()); 104 | }; 105 | 106 | msrcryptoSha1.deleteInstance = function(id) { 107 | msrcryptoSha1.instances[id] = null; 108 | delete msrcryptoSha1.instances[id]; 109 | }; 110 | 111 | msrcryptoSha1.hash = function(/*@dynamic*/p) { 112 | 113 | if (p.operationSubType === "process") { 114 | msrcryptoSha1.sha1.process(p.buffer); 115 | return; 116 | } 117 | 118 | if (p.operationSubType === "finish") { 119 | return msrcryptoSha1.sha1.finish(); 120 | } 121 | 122 | return msrcryptoSha1.sha1().computeHash(p.buffer); 123 | 124 | }; 125 | 126 | operations.register("digest", "SHA-1", msrcryptoSha1.hash); 127 | 128 | } 129 | 130 | msrcryptoHashFunctions["SHA-1"] = msrcryptoSha1.sha1; 131 | -------------------------------------------------------------------------------- /scripts/sha256.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: no-bitwise 20 | 21 | var msrcryptoSha256 = (function() { 22 | 23 | var utils = msrcryptoUtilities; 24 | 25 | function hashBlock(message, blockIndex, hv, k, w) { 26 | /// 27 | /// Block function for hashing algorithm to use. 28 | /// 29 | /// Block data to hash 30 | /// The block of the data to hash 31 | /// Initial hash values 32 | /// K constants 33 | /// Buffer for w values 34 | /// Updated initial hash values 35 | 36 | var t, i, temp, x0, x1, blockSize = 64, mask = 0xFFFFFFFF; 37 | 38 | var ra = hv[0], 39 | rb = hv[1], 40 | rc = hv[2], 41 | rd = hv[3], 42 | re = hv[4], 43 | rf = hv[5], 44 | rg = hv[6], 45 | rh = hv[7]; 46 | 47 | // 0 ≤ t ≤ 15 48 | for (i = 0; i < 16; i++) { 49 | w[i] = utils.bytesToInt32(message, blockIndex * blockSize + i * 4); 50 | } 51 | 52 | // 16 ≤ t ≤ 63 53 | for (t = 16; t < 64; t++) { 54 | 55 | x0 = w[t - 15]; 56 | x1 = w[t - 2]; 57 | 58 | w[t] = (((x1 >>> 17) | (x1 << 15)) ^ ((x1 >>> 19) | (x1 << 13)) ^ (x1 >>> 10)) 59 | + w[t - 7] 60 | + (((x0 >>> 7) | (x0 << 25)) ^ ((x0 >>> 18) | (x0 << 14)) ^ (x0 >>> 3)) 61 | + w[t - 16]; 62 | 63 | w[t] = w[t] & mask; 64 | } 65 | 66 | for (i = 0; i < 64; i++) { 67 | 68 | temp = rh + 69 | ((re >>> 6 | re << 26) ^ (re >>> 11 | re << 21) ^ (re >>> 25 | re << 7)) + 70 | ((re & rf) ^ ((~re) & rg)) + 71 | k[i] + w[i]; 72 | 73 | rd += temp; 74 | 75 | temp += ((ra >>> 2 | ra << 30) ^ (ra >>> 13 | ra << 19) ^ (ra >>> 22 | ra << 10)) + 76 | ((ra & (rb ^ rc)) ^ (rb & rc)); 77 | 78 | rh = rg; // 'h' = g 79 | rg = rf; // 'g' = f 80 | rf = re; // 'f' = e 81 | re = rd; // 'e' = d 82 | rd = rc; // 'd' = c 83 | rc = rb; // 'c' = b 84 | rb = ra; // 'b' = a 85 | ra = temp; // 'a' = temp 86 | 87 | } 88 | 89 | hv[0] = (hv[0] + ra) >>> 0; 90 | hv[1] = (hv[1] + rb) >>> 0; 91 | hv[2] = (hv[2] + rc) >>> 0; 92 | hv[3] = (hv[3] + rd) >>> 0; 93 | hv[4] = (hv[4] + re) >>> 0; 94 | hv[5] = (hv[5] + rf) >>> 0; 95 | hv[6] = (hv[6] + rg) >>> 0; 96 | hv[7] = (hv[7] + rh) >>> 0; 97 | 98 | return hv; 99 | } 100 | 101 | var k256, h224, h256, der224, der256, upd = utils.unpackData; 102 | 103 | h224 = upd("wQWe2DZ81QcwcN0X9w5ZOf/ACzFoWBURZPmPp776T6Q", 4, 1); 104 | 105 | h256 = upd("agnmZ7tnroU8bvNypU/1OlEOUn+bBWiMH4PZq1vgzRk", 4, 1); 106 | 107 | // tslint:disable-next-line: max-line-length 108 | k256 = upd("QoovmHE3RJG1wPvP6bXbpTlWwltZ8RHxkj+CpKscXtXYB6qYEoNbASQxhb5VDH3Dcr5ddIDesf6b3AanwZvxdOSbacHvvkeGD8GdxiQMocwt6SxvSnSEqlywqdx2+YjamD5RUqgxxm2wAyfIv1l/x8bgC/PVp5FHBspjURQpKWcntwqFLhshOE0sbfxTOA0TZQpzVHZqCruBwskuknIshaK/6KGoGmZLwkuLcMdsUaPRkugZ1pkGJPQONYUQaqBwGaTBFh43bAgnSHdMNLC8tTkcDLNO2KpKW5zKT2gub/N0j4LueKVjb4TIeBSMxwIIkL7/+qRQbOu++aP3xnF48g", 4, 1); 109 | 110 | // SHA-224 DER encoding 111 | // 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C 112 | der224 = upd("MC0wDQYJYIZIAWUDBAIEBQAEHA"); 113 | 114 | // SHA-256 DER encoding 115 | // 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 116 | der256 = upd("MDEwDQYJYIZIAWUDBAIBBQAEIA"); 117 | 118 | return { 119 | sha224: function() { 120 | return msrcryptoSha("SHA-224", der224, h224, k256, 64, hashBlock, 224); 121 | }, 122 | sha256: function() { 123 | return msrcryptoSha("SHA-256", der256, h256, k256, 64, hashBlock, 256); 124 | } 125 | }; 126 | })(); 127 | 128 | if (typeof operations !== "undefined") { 129 | 130 | // Create a new instance if there isn't already one 131 | msrcryptoSha256.instance224 = msrcryptoSha256.instance224 || msrcryptoSha256.sha224(); 132 | msrcryptoSha256.instance256 = msrcryptoSha256.instance256 || msrcryptoSha256.sha256(); 133 | 134 | // Store separate instances for each worker when using 'process' streaming 135 | msrcryptoSha256.instances = {}; 136 | 137 | msrcryptoSha256.getInstance224 = function(id) { 138 | return msrcryptoSha256.instances[id] || (msrcryptoSha256.instances[id] = msrcryptoSha256.sha224()); 139 | }; 140 | 141 | msrcryptoSha256.getInstance256 = function(id) { 142 | return msrcryptoSha256.instances[id] || (msrcryptoSha256.instances[id] = msrcryptoSha256.sha256()); 143 | }; 144 | 145 | msrcryptoSha256.deleteInstance = function(id) { 146 | msrcryptoSha256.instances[id] = null; 147 | delete msrcryptoSha256.instances[id]; 148 | }; 149 | 150 | msrcryptoSha256.hash256 = function(/*@dynamic*/p) { 151 | 152 | if (p.operationSubType === "process") { 153 | msrcryptoSha256.getInstance256(p.workerid).process(p.buffer); 154 | return null; 155 | } 156 | 157 | if (p.operationSubType === "finish") { 158 | 159 | var result = msrcryptoSha256.getInstance256(p.workerid).finish(); 160 | msrcryptoSha256.deleteInstance(p.workerid); 161 | return result; 162 | } 163 | 164 | if (p.operationSubType === "abort") { 165 | msrcryptoSha256.deleteInstance(p.workerid); 166 | return; 167 | } 168 | 169 | return msrcryptoSha256.instance256.computeHash(p.buffer); 170 | 171 | }; 172 | 173 | msrcryptoSha256.hash224 = function(/*@dynamic*/p) { 174 | 175 | if (p.operationSubType === "process") { 176 | msrcryptoSha256.getInstance224(p.workerid).process(p.buffer); 177 | return; 178 | } 179 | 180 | if (p.operationSubType === "finish") { 181 | var result = msrcryptoSha256.getInstance224(p.workerid).finish(); 182 | } 183 | 184 | if (p.operationSubType === "abort") { 185 | msrcryptoSha224.deleteInstance(p.workerid); 186 | return; 187 | } 188 | 189 | return msrcryptoSha256.instance224.computeHash(p.buffer); 190 | 191 | }; 192 | 193 | operations.register("digest", "SHA-224", msrcryptoSha256.hash224); 194 | operations.register("digest", "SHA-256", msrcryptoSha256.hash256); 195 | } 196 | 197 | msrcryptoHashFunctions["SHA-224"] = msrcryptoSha256.sha224; 198 | msrcryptoHashFunctions["SHA-256"] = msrcryptoSha256.sha256; 199 | -------------------------------------------------------------------------------- /scripts/subtle/head.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var msrcryptoSubtle; 20 | 21 | // This code is not used in web worker instance. 22 | //if (!runningInWorkerInstance) { 23 | 24 | var utils = msrcryptoUtilities; 25 | 26 | msrcryptoSubtle = (function() { -------------------------------------------------------------------------------- /scripts/subtle/keyManager.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // Storage for the keyData. 20 | // Stored as {keyHandle: keyHandle, keyData: keyData} objects. 21 | var keys = []; 22 | 23 | keys.add = function(keyHandle, keyData) { 24 | keys.push({ keyHandle: keyHandle, keyData: keyData }); 25 | }; 26 | 27 | keys.remove = function(keyHandle) { 28 | for (var i = 0; i < keys.length; i += 1) { 29 | if (keys[i].keyHandle === keyHandle) { 30 | keys = keys.splice(i, 1); 31 | return; 32 | } 33 | } 34 | }; 35 | 36 | keys.lookup = function(keyHandle) { 37 | for (var i = 0; i < keys.length; i += 1) { 38 | if (keys[i].keyHandle === keyHandle) { 39 | return keys[i].keyData; 40 | } 41 | } 42 | return null; 43 | }; 44 | -------------------------------------------------------------------------------- /scripts/subtle/operations.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var streamObject = function(op) { 20 | 21 | return { 22 | process: function(buffer) { 23 | return op.process(buffer); 24 | }, 25 | finish: function() { 26 | return op.finish(); 27 | }, 28 | abort: function() { 29 | return op.abort(); 30 | } 31 | }; 32 | }; 33 | 34 | function baseOperation(processResults) { 35 | 36 | var result = null, 37 | oncompleteCallback = null, 38 | onerrorCallback = null, 39 | retObj, 40 | promise, 41 | resolveFunc, 42 | rejectFunc; 43 | 44 | // Create a new promise 45 | promise = new Promise( 46 | function(resolve, reject) { 47 | resolveFunc = resolve; 48 | rejectFunc = reject; 49 | }); 50 | // Called when the worker returns a result 51 | function opDispatchEvent( /*@type(Event)*/ e) { 52 | // We have 4 possible result scenarios 53 | 54 | // 1. Error - call the onError callback 55 | if (e.type === "error") { 56 | // If the onerror callback has been set, call it. 57 | if (rejectFunc) { 58 | e.data && (e.data.stack = "Error") && (e.data.code = 0); 59 | rejectFunc.apply(promise, [e.data || e]); 60 | } 61 | return; 62 | } 63 | 64 | // 2. Process w/ result 65 | // used when streaming encryption. we get a partial result back. 66 | if (e.data.type === "process") { 67 | processResults(e.data.result, true); 68 | return; 69 | } 70 | 71 | // 3. Finish 72 | // the last step of streaming. it will always have a result. 73 | if (e.data.type === "finish") { 74 | processResults(e.data.result, true); 75 | return; 76 | } 77 | 78 | // 4. Full Operation 79 | // a full crypto operation. it will always have a result. 80 | // Resolve the operation promise with the result 81 | this.result = processResults(e.data); 82 | resolveFunc.apply(promise, [this.result]); 83 | 84 | return; 85 | } 86 | 87 | retObj = { 88 | dispatchEvent: opDispatchEvent, 89 | promise: promise, 90 | result: null 91 | }; 92 | 93 | return retObj; 94 | } 95 | 96 | function keyOperation() { 97 | 98 | function processResult(result) { 99 | 100 | var publicKey, 101 | privateKey; 102 | 103 | // Could be the result of an import, export, generate. 104 | // Get the keyData and keyHandle out. 105 | switch (result.type) { 106 | 107 | // KeyImport: save the new key 108 | case "keyGeneration": 109 | case "keyImport": 110 | case "keyDerive": 111 | if (result.keyPair) { 112 | keys.add(result.keyPair.publicKey.keyHandle, result.keyPair.publicKey.keyData); 113 | keys.add(result.keyPair.privateKey.keyHandle, result.keyPair.privateKey.keyData); 114 | return { 115 | publicKey: result.keyPair.publicKey.keyHandle, 116 | privateKey: result.keyPair.privateKey.keyHandle 117 | }; 118 | } else { 119 | keys.add(result.keyHandle, result.keyData); 120 | return result.keyHandle; 121 | } 122 | 123 | // KeyExport: return the export data 124 | case "keyExport": 125 | return result.keyHandle; 126 | 127 | case "keyPairGeneration": 128 | privateKey = result.keyPair.privateKey; 129 | publicKey = result.keyPair.publicKey; 130 | keys.add(publicKey.keyHandle, publicKey.keyData); 131 | keys.add(privateKey.keyHandle, privateKey.keyData); 132 | return { 133 | publicKey: publicKey.keyHandle, 134 | privateKey: privateKey.keyHandle 135 | }; 136 | 137 | default: 138 | throw new Error("Unknown key operation"); 139 | } 140 | } 141 | 142 | return baseOperation(processResult); 143 | } 144 | 145 | function toArrayBufferIfSupported(dataArray) { 146 | 147 | // If the browser supports typed-arrays, return an ArrayBuffer like IE11. 148 | if (typedArraySupport && dataArray.pop) { 149 | 150 | // We can't write to an ArrayBuffer directly so we create a Uint8Array 151 | // and return it's buffer property. 152 | return (new Uint8Array(dataArray)).buffer; 153 | } 154 | 155 | // Do nothing and just return the passed-in array. 156 | return dataArray; 157 | } 158 | 159 | function cryptoOperation(cryptoContext) { 160 | 161 | function processResult(result, isProcessCall) { 162 | 163 | // If the browser supports typed-arrays, return an ArrayBuffer like IE11. 164 | // result may be null when a Process() call returns for a crypto operation 165 | // that does not support intermediate values (i.e. sha-256 can be called 166 | // using streaming, but will not return intermediate results with process.) 167 | result = result && toArrayBufferIfSupported(result); 168 | 169 | if (isProcessCall) { 170 | promiseQueue.resolve(result); 171 | return; 172 | } 173 | 174 | // A normal array will be returned. 175 | return result; 176 | } 177 | 178 | var promiseQueue = [], 179 | op = baseOperation(processResult); 180 | 181 | op.stream = cryptoContext.algorithm.stream; 182 | 183 | promiseQueue.add = function(label) { 184 | 185 | var resolveFunc, 186 | rejectFunc, 187 | promise = new Promise( 188 | function(resolve, reject) { 189 | resolveFunc = resolve; 190 | rejectFunc = reject; 191 | }); 192 | 193 | promise.label = label; 194 | 195 | promiseQueue.push({ 196 | resolve: resolveFunc, 197 | reject: rejectFunc, 198 | promise: promise 199 | }); 200 | 201 | return promise; 202 | }; 203 | 204 | promiseQueue.resolve = function(result) { 205 | var queueItem = promiseQueue.shift(); 206 | queueItem.resolve.apply(queueItem.promise, [result]); 207 | }; 208 | 209 | op.process = function(buffer) { 210 | cryptoContext.operationSubType = "process"; 211 | cryptoContext.buffer = utils.toArray(buffer); 212 | workerManager.continueJob(this, 213 | utils.clone(cryptoContext)); 214 | 215 | return promiseQueue.add("process"); 216 | }; 217 | 218 | op.finish = function() { 219 | cryptoContext.operationSubType = "finish"; 220 | cryptoContext.buffer = []; 221 | workerManager.continueJob(this, 222 | utils.clone(cryptoContext)); 223 | 224 | return promiseQueue.add("finish"); 225 | }; 226 | 227 | op.abort = function() { 228 | workerManager.abortJob(this); 229 | }; 230 | op.algorithm = cryptoContext.algorithm || null; 231 | op.key = cryptoContext.keyHandle || null; 232 | 233 | return op; 234 | } 235 | -------------------------------------------------------------------------------- /scripts/subtle/syncWorker.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // This worker is used when webworkers aren't available. 20 | // It will function synchronously but use the same 21 | // mechanisms that the asynchronous webworkers use. 22 | function syncWorker() { 23 | var result; 24 | 25 | // PostMessage is how you interact with a worker. You post some data to the worker 26 | // and it will process it and return it's data to the onmessage function. 27 | // Since we're really running synchronously, we call the crypto function in 28 | // PostMessage and wait for the result. Then we call the OnMessage function with 29 | // that result. This will give the same behavior as a web-worker. 30 | function postMessage(data) { 31 | 32 | // Web-workers will automatically return an error message when an 33 | // error is thrown within the web worker. 34 | // When using a sync worker, we'll have to catch thrown errors, so we 35 | // need a try/catch block here. 36 | try { 37 | // add the workerid to the parameters. when streaming multiple crypto operations that 38 | // call the same functions (i.e. sha-256 & hmac-256) we need a way to 39 | // maintain separate instances. we use the worker id for this. 40 | data.workerid = this.id; 41 | result = msrcryptoWorker.jsCryptoRunner({ data: data }); 42 | } catch (ex) { 43 | this.onerror({ data: ex, type: "error" }); 44 | return; 45 | } 46 | 47 | this.onmessage({ data: result }); 48 | } 49 | 50 | return { 51 | postMessage: postMessage, 52 | onmessage: null, 53 | onerror: null, 54 | terminate: function() { 55 | // This is a no-op to be compatible with webworker. 56 | } 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /scripts/subtle/tail.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | return { 20 | publicMethods : publicMethods, 21 | internalMethods: internalMethods}; 22 | 23 | }) (); 24 | -------------------------------------------------------------------------------- /scripts/testInterface.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | var testInterface = (function() { 20 | 21 | return { 22 | cryptoMath: cryptoMath, 23 | rsa: msrcryptoRsa, 24 | hashFunctions : msrcryptoHashFunctions, 25 | sha1: msrcryptoSha1.sha1, 26 | sha256: msrcryptoSha256.sha256, 27 | cryptoECC: cryptoECC, 28 | utilities: msrcryptoUtilities, 29 | entropy: MsrcryptoEntropy, 30 | random: msrcryptoPseudoRandom, 31 | ecdsa: msrcryptoEcdsa 32 | }; 33 | 34 | })(); 35 | -------------------------------------------------------------------------------- /scripts/testVectors/tv_prng.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // tslint:disable: max-line-length 20 | 21 | // These Known Answer Tests (KAT) are taken from Windows CNG FIPS 140-2 verification effort, 22 | // which was provided by Windows CNG FIPS certification lab (CMVP) for AES-256 no derivation function. 23 | var prngKAT = [ 24 | { 25 | seed: [0x2c, 0xb1, 0xca, 0x81, 0x54, 0xee, 0x07, 0x12, 26 | 0x3b, 0x04, 0x11, 0x74, 0x64, 0xd7, 0xea, 0xe0, 27 | 0x8a, 0x38, 0x48, 0xac, 0x62, 0x51, 0x6e, 0x50, 28 | 0x94, 0x50, 0x46, 0xb9, 0xf6, 0x51, 0xc1, 0xd2, 29 | 0x0a, 0x8f, 0x72, 0x4e, 0xb9, 0xcd, 0x67, 0xb9, 30 | 0x50, 0x00, 0x4a, 0xc0, 0xb9, 0x40, 0xb7, 0xbe], 31 | personalizationString: [], 32 | additionalInput: [ 33 | [], 34 | [0x0b, 0xd2, 0xc2, 0x7f, 0x45, 0x83, 0x3e, 0x83, 0x49, 0x07, 0xa6, 0x61, 0x15, 0xee, 0xee, 0x82, 35 | 0xd3, 0x64, 0x83, 0x27, 0xbf, 0x3b, 0x44, 0x16, 0x3d, 0x38, 0xc0, 0x84, 0x34, 0x9c, 0xaf, 0x43, 36 | 0xaf, 0xf5, 0xb5, 0x2f, 0xb5, 0x25, 0x54, 0xd5, 0x66, 0xb2, 0x31, 0x64, 0x59, 0x4e, 0x8a, 0xd7], 37 | [], 38 | [0xc8, 0x8e, 0xa3, 0x32, 0xfd, 0x61, 0x98, 0x54, 0xc4, 0xb5, 0x5f, 0xbf, 0x99, 0x31, 0x7c, 0x42, 39 | 0x70, 0x52, 0x2a, 0x18, 0xc7, 0x6b, 0x08, 0x08, 0xea, 0xdc, 0x07, 0xbc, 0x88, 0x91, 0x93, 0x61, 40 | 0x75, 0xbd, 0xff, 0x7f, 0xc0, 0xd6, 0x34, 0x18, 0xf7, 0xd2, 0x9b, 0x06, 0xb8, 0xa2, 0x49, 0x90] 41 | ], 42 | expected: [ 43 | [0xf5, 0x0a, 0x61, 0x80, 0xff, 0xf3, 0x7e, 0x07, 0xa7, 0x03, 0xcb, 0x09, 0x05, 0x0a, 0x54, 0x78], 44 | [0x2b, 0xf0, 0xc5, 0x45, 0x9e, 0x65, 0x21, 0x17, 0xc6, 0xd1, 0x68, 0x13, 0x41, 0x08, 0x69, 0xbe, 45 | 0xe7, 0x18, 0x80, 0x47, 0xd4, 0x55, 0x3b, 0x85, 0xbc, 0x9d, 0x32, 0x7d, 0x83, 0x0e, 0x3c, 0xeb], 46 | [0xd5, 0x82, 0x38, 0xbe, 0x3b, 0x63, 0x00, 0xb3, 0xcb, 0xdf, 0xcf, 0x29, 0x82, 0x42, 0x01, 0xda, 47 | 0x55, 0x3f, 0xe8, 0x18, 0x24, 0x0b, 0x3c, 0xec, 0x7b, 0xc7, 0x03, 0x0a, 0xcd, 0x12, 0x60, 0x7b, 48 | 0xbb, 0xee, 0xda, 0xa8, 0x4c, 0x24, 0xaf, 0x22, 0x36, 0xcd, 0x4a, 0xa6, 0xf7, 0x6f, 0x01, 0x75], 49 | [0xb4, 0xcb, 0x2b, 0x9e, 0x50, 0x5d, 0xe7, 0x21, 0xc1, 0x6e, 0xe0, 0x37, 0x92, 0x4f, 0x4e, 0x93, 50 | 0x02, 0x42, 0x5b, 0xdc, 0xad, 0x66, 0xad, 0x96, 0x62, 0xf2, 0xf9, 0xf7, 0x7e, 0x7c, 0xd9, 0xbf, 51 | 0x16, 0xfc, 0x9d, 0x70, 0xae, 0xa8, 0x11, 0x2b, 0xb1, 0xb9, 0x94, 0x0c, 0xcc, 0x9c, 0xc6, 0xfd, 52 | 0x0d, 0x07, 0x19, 0x18, 0xf2, 0x05, 0x50, 0x6a, 0xb6, 0xf4, 0x7a, 0x37, 0xef, 0xeb, 0x54, 0x20] 53 | ] 54 | }, 55 | { 56 | seed: [0x22, 0xb3, 0xdb, 0xce, 0xbf, 0xa2, 0x40, 0x31, 0x4f, 0x30, 0xe6, 0x00, 0x8e, 0x04, 0x67, 0xc4, 57 | 0xa1, 0xa2, 0x67, 0x01, 0xaa, 0x38, 0x4f, 0xa4, 0xab, 0xad, 0x50, 0xac, 0x9e, 0xe6, 0x96, 0x1a, 58 | 0xd4, 0x5a, 0xca, 0x1d, 0x8d, 0xd7, 0xcd, 0x78, 0xd7, 0x94, 0xb1, 0x35, 0xaa, 0x7a, 0xf9, 0x8f], 59 | personalizationString: [0xdb, 0x99, 0xa3, 0x97, 0x5f, 0xdd, 0x0a, 0x7c, 0x5f, 0x4b, 0x48, 0xea, 0x07, 0x8e, 0x73, 0xbf, 60 | 0xdf, 0x8a, 0x8f, 0xde, 0xc0, 0x06, 0xab, 0x7e, 0x13, 0x9a, 0x38, 0xb3, 0x4a, 0xda, 0xab, 0x3c, 61 | 0xa2, 0xc2, 0x55, 0x8d, 0x19, 0x62, 0x80, 0x1f, 0xac, 0xcc, 0xcd, 0xf5, 0xd5, 0x3d, 0xcb, 0x71], 62 | additionalInput: [ 63 | [], 64 | [0x51, 0x81, 0xed, 0x05, 0xaa, 0x1f, 0x8f, 0x9c, 0x2c, 0x22, 0x93, 0x04, 0xe0, 0x42, 0xb8, 0xe0, 65 | 0x5e, 0x08, 0x20, 0xb7, 0x4a, 0xf6, 0xee, 0xb7, 0x10, 0xf9, 0x24, 0xc4, 0xdd, 0x12, 0xbc, 0xc7, 66 | 0xe0, 0x42, 0x07, 0x33, 0xc1, 0xb5, 0x45, 0xda, 0x61, 0x31, 0x84, 0xf0, 0xd2, 0xbf, 0xbc, 0x5e] 67 | ], 68 | expected: [ 69 | [0xc4, 0x6a, 0x1c, 0xe8, 0xcc, 0x00, 0x8d, 0x73, 0xc3, 0x44, 0xd2, 0x3c, 0x93, 0x1f, 0x30, 0x9a, 70 | 0xa3, 0xf2, 0x91, 0x35, 0x53, 0x64, 0xb4, 0x36, 0x3b, 0x02, 0xfb, 0xd4, 0xba, 0x9d, 0xda, 0xda, 71 | 0x78, 0x03, 0x2f, 0x8c, 0xf3, 0x98, 0x26, 0xf8, 0x4d, 0x18, 0x2e, 0x86, 0x55, 0x9e, 0x80, 0x5b, 72 | 0x0f, 0x17, 0x87, 0x93, 0x0e, 0xf6, 0x1b, 0x99, 0xec, 0xfd, 0xe1, 0xba, 0x76, 0x37, 0x91, 0xbb, 73 | 0xa9, 0xd9, 0x88, 0x00, 0x7b, 0x30, 0xca, 0xaf, 0x11, 0x2c, 0xfa, 0x3f, 0x05, 0xbc, 0x24, 0xb8, 74 | 0xe4, 0x0f, 0x8a, 0xe2, 0xd8, 0x27, 0xa7, 0xe5, 0x8c, 0x4f, 0xe0, 0xfb, 0x3b, 0x30, 0x6c, 0x19, 75 | 0xef, 0xfd, 0xff, 0x94, 0x38, 0x8f, 0xdd, 0x38, 0x4f, 0x2a, 0xd6, 0x4b, 0x23, 0xc5, 0x44, 0xd1, 76 | 0x0e, 0x52, 0x7c, 0x1b, 0xaa, 0xf9, 0x69, 0x4e, 0x86, 0x19, 0x99, 0x70, 0x12, 0xfc, 0x77, 0xdd, 77 | 0x91, 0x85, 0x8f, 0x9a, 0xc9, 0xf9, 0x40, 0x64, 0x99, 0xc7, 0x22, 0xa2, 0x34, 0x79, 0x7d, 0x95, 78 | 0x2c, 0xa0, 0x84, 0xe9, 0x4a, 0xa3, 0xe0, 0x84, 0x7c, 0x37, 0x52, 0x74, 0xe1, 0x48, 0x41, 0x81, 79 | 0x4b, 0x84, 0x82, 0x0d, 0x6e, 0xa6, 0x0e, 0xc4, 0x12, 0xa4, 0xc1, 0x2a, 0x01, 0x31, 0xd5, 0x74, 80 | 0x9c, 0x85, 0xc4, 0x00, 0xb6, 0xf8, 0xb8, 0x7e, 0x41, 0xbd, 0x71, 0x17, 0xcf, 0xea, 0x7a, 0xab, 81 | 0x58, 0xe7, 0x1f, 0x14, 0x09, 0x9e, 0x10, 0xf8, 0xba, 0x76, 0x81, 0xa2, 0x0f, 0xdb, 0x5c, 0x30, 82 | 0xc7, 0x87, 0x7d, 0x7c, 0x77, 0x59, 0x09, 0x3f, 0xa4, 0x06, 0xbe, 0xb8, 0xb9, 0xbd, 0xab, 0xe7], 83 | [0xf7, 0xd3, 0x0c, 0x72, 0xa4, 0x45, 0xf1, 0x85, 0x79, 0x42, 0xd0, 0x04, 0x93, 0xe5, 0xe5, 0x90, 84 | 0x4c, 0x59, 0xb5, 0x9e, 0xac, 0x51, 0x4e, 0xde, 0x5f, 0x09, 0x4c, 0x25, 0x99, 0xea, 0xae, 0x1b, 85 | 0x78, 0x67, 0x0c, 0x94, 0x27, 0xb9, 0xb6, 0xbc, 0x1a, 0xce, 0x72, 0x75, 0x6d, 0x8e, 0xc6, 0x47, 86 | 0x39, 0x87, 0xa0, 0xa3, 0x63, 0x1f, 0xdc, 0x98, 0x94, 0x32, 0x0c, 0x31, 0x7d, 0xa3, 0xaa, 0xb5, 87 | 0xde, 0x3b, 0x64, 0x39, 0x75, 0x99, 0x81, 0xab, 0xfe, 0x19, 0x60, 0xea, 0x33, 0x4c, 0x8b, 0x42, 88 | 0x7f, 0x4b, 0x83, 0xb8, 0xe2, 0x18, 0x83, 0xa7, 0x67, 0x49, 0x2c, 0xd4, 0x9f, 0xf4, 0x11, 0x62, 89 | 0x51, 0x75, 0xed, 0x1e, 0xd7, 0xcd, 0x9e, 0xfe, 0xa9, 0xea, 0xe7, 0xad, 0xe5, 0x1f, 0x94, 0xc9, 90 | 0x69, 0x88, 0xe9, 0xa7, 0x75, 0x5b, 0x4f, 0x10, 0xb3, 0x4a, 0xf2, 0x6b, 0x9d, 0xce, 0xa5, 0xc1, 91 | 0x53, 0xce, 0x11, 0xd6, 0xb6, 0xde, 0x32, 0x37, 0xf6, 0xf9, 0x2b, 0x5f, 0x43, 0x4e, 0x37, 0x2b, 92 | 0xba, 0xeb, 0x2e, 0x25, 0xac, 0xed, 0x3f, 0x08, 0xc2, 0xbe, 0xe3, 0x78, 0x91, 0x82, 0x60, 0xbd, 93 | 0x83, 0xa8, 0x40, 0x61, 0xbe, 0xce, 0x6d, 0x6e, 0x78, 0xc4, 0x0b, 0xbd, 0x1f, 0x01, 0x73, 0xf0, 94 | 0x9a, 0xf6, 0xed, 0xd1, 0x8f, 0xa3, 0xfe, 0xe9, 0x55, 0x8e, 0x8f, 0x66, 0xc4, 0x78, 0xe4, 0x6c, 95 | 0xa5, 0xd1, 0xbf, 0xce, 0xd1, 0xb6, 0x71, 0x06, 0x80, 0x89, 0xe0, 0xc6, 0x13, 0x23, 0x6b, 0x75, 96 | 0xd5, 0x57, 0x0d, 0xa2, 0x91, 0xcb, 0x05, 0xf5, 0xb8, 0x35, 0xdd, 0x86, 0x74, 0xe8, 0x3e, 0x37, 97 | 0xc6, 0xe7, 0x8b, 0x4b, 0x0b, 0x71, 0x76, 0x12, 0x70, 0x82, 0x06, 0xa6, 0x01, 0xb0, 0x6a, 0x9d] 98 | ] 99 | } 100 | ]; 101 | -------------------------------------------------------------------------------- /scripts/tests/Test.Aes.Cbc.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | aesCbcTests(); 22 | 23 | function aesCbcTests() { 24 | 25 | QUnit.module( "AES-CBC" ); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | var usages = [["encrypt", "decrypt"], ["encrypt"], ["decrypt"], ["decrypt", "encrypt"]]; 30 | 31 | QUnit.test( label + " key import/export raw 128 ", function( assert ) { 32 | ts.keyImportExportTest( aes.cbc._128.raw, usages, undefined, context( iterations, assert ) ); 33 | } ); 34 | 35 | QUnit.test( label + " key import/export raw 192 ", function( assert ) { 36 | ts.keyImportExportTest( aes.cbc._192.raw, usages, undefined, context( iterations, assert ) ); 37 | } ); 38 | 39 | QUnit.test( label + " key import/export raw 256 ", function( assert ) { 40 | ts.keyImportExportTest( aes.cbc._256.raw, usages, undefined, context( iterations, assert ) ); 41 | } ); 42 | 43 | QUnit.test( label + " key import/export jwk 128 ", function( assert ) { 44 | ts.keyImportExportTest( aes.cbc._128.jwk, undefined, undefined, context( iterations, assert ) ); 45 | } ); 46 | 47 | QUnit.test( label + " key import/export jwk 192 ", function( assert ) { 48 | ts.keyImportExportTest( aes.cbc._192.jwk, undefined, undefined, context( iterations, assert ) ); 49 | } ); 50 | 51 | QUnit.test( label + " key import/export jwk 256 ", function( assert ) { 52 | ts.keyImportExportTest( aes.cbc._256.jwk, undefined, undefined, context( iterations, assert ) ); 53 | } ); 54 | 55 | QUnit.test( label + " generateKeyTest 128", function( assert ) { 56 | ts.keyGenerateTest( aesCbcKeyAlg( 128 ), usages, inspectAesCbcKey, context( iterations, assert ) ); 57 | } ); 58 | 59 | QUnit.test( label + " generateKeyTest 192", function( assert ) { 60 | ts.keyGenerateTest( aesCbcKeyAlg( 192 ), usages, inspectAesCbcKey, context( iterations, assert ) ); 61 | } ); 62 | 63 | QUnit.test( label + " generateKeyTest 256", function( assert ) { 64 | ts.keyGenerateTest( aesCbcKeyAlg( 256 ), usages, inspectAesCbcKey, context( iterations, assert ) ); 65 | } ); 66 | 67 | QUnit.test( label + " encrypt/decrypt 128", function( assert ) { 68 | ts.encryptDecryptTest( aesCbcKeyAlg( 128 ), aesCbcEncryptAlg, context( iterations, assert ) ); 69 | } ); 70 | 71 | QUnit.test( label + " encrypt/decrypt 192", function( assert ) { 72 | ts.encryptDecryptTest( aesCbcKeyAlg( 192 ), aesCbcEncryptAlg, context( iterations, assert ) ); 73 | } ); 74 | 75 | QUnit.test( label + " encrypt/decrypt 256", function( assert ) { 76 | ts.encryptDecryptTest( aesCbcKeyAlg( 256 ), aesCbcEncryptAlg, context( iterations, assert ) ); 77 | } ); 78 | 79 | QUnit.test(label + " decrypt native ciphers 128", function(assert) { 80 | ts.decryptNativeCiphersTest(aes.cbc._128.ciphers, context(Math.min(aes.cbc._128.ciphers.vectors.length, iterations), assert)); 81 | }); 82 | 83 | QUnit.test(label + " decrypt native ciphers 192", function(assert) { 84 | ts.decryptNativeCiphersTest(aes.cbc._192.ciphers, context(Math.min(aes.cbc._192.ciphers.vectors.length, iterations), assert)); 85 | }); 86 | 87 | QUnit.test(label + " decrypt native ciphers 256", function(assert) { 88 | ts.decryptNativeCiphersTest(aes.cbc._256.ciphers, context(Math.min(aes.cbc._256.ciphers.vectors.length, iterations), assert)); 89 | }); 90 | 91 | } 92 | 93 | // AES-CBC specific key property validation 94 | function inspectAesCbcKey( keyObj, algorithm, usages, reason /* set reason.message to return fail messages */ ) { 95 | 96 | var fail = []; 97 | 98 | if ( !validation.prop.string( keyObj, "alg", "A" + algorithm.length + "CBC" ) ) { 99 | fail.push( "key.alg !== A" + algorithm.length + "CBC" ); 100 | } 101 | 102 | if ( !validation.prop.boolean( keyObj, "ext", true ) ) { 103 | fail.push( "key.ext !== true" ); 104 | } 105 | 106 | if ( !validation.prop.string( keyObj, "k", /^([A-Za-z0-9-_]+)$/ /* base64url */ ) ) { 107 | fail.push( "key.k not base64url" ); 108 | } 109 | 110 | // k property converts to bytes array of expected length 111 | var kBytes = msrCrypto.fromBase64( keyObj.k ); 112 | if ( !testShared.isBytes( kBytes, algorithm.length / 8 ) ) { 113 | fail.push( "key.k is not bytes" ); 114 | } 115 | 116 | // has key_ops property with expected usages 117 | if ( Object.prototype.toString.call( keyObj.key_ops ) !== "[object Array]" ) { 118 | fail.push( "key.key_ops missing or not Array" ); 119 | } 120 | 121 | if ( keyObj.key_ops && !testShared.compareUsages( keyObj.key_ops, usages ) ) { 122 | fail.push( "key.key_ops invalid usage(s)" ); 123 | } 124 | 125 | if ( !validation.prop.string( keyObj, "kty", "oct" ) ) { 126 | fail.push( "key.kty !== oct" ); 127 | } 128 | 129 | reason.message = fail.join( "; " ); 130 | 131 | return ( fail.length === 0 ); 132 | } 133 | 134 | // Generates a new encrypt/decrypt alg 135 | function aesCbcEncryptAlg() { 136 | return { 137 | name: "AES-CBC", 138 | iv: testShared.arr( testShared.getRandomBytes( 16 ) ) 139 | }; 140 | } 141 | 142 | function aesCbcKeyAlg( length ) { 143 | return { 144 | name: "AES-CBC", 145 | length: length 146 | }; 147 | } 148 | -------------------------------------------------------------------------------- /scripts/tests/Test.Aes.Gcm.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | // NOTE: 22 | // 23 | // Microsoft Edge : 24 | // does not support 32 or 64 bit tag lengths 25 | // will fail on jwk keys with 'short' data elements (truncated leading zeros resulting in shorter data array) 26 | // 27 | // Chrome : 28 | // does not support 192 bit AES keys 29 | // 30 | 31 | aesGcmTests(); 32 | 33 | function aesGcmTests() { 34 | 35 | QUnit.module( "AES-GCM" ); 36 | 37 | var ts = testShared; 38 | var context = ts.testContext; 39 | var usages = [["encrypt", "decrypt"], ["encrypt"], ["decrypt"], ["decrypt", "encrypt"]]; 40 | 41 | QUnit.test( label + " key import/export raw 128 ", function( assert ) { 42 | ts.keyImportExportTest( aes.gcm._128.raw, usages, undefined, context( iterations, assert ) ); 43 | } ); 44 | 45 | QUnit.test( label + " key import/export raw 192 ", function( assert ) { 46 | ts.keyImportExportTest( aes.gcm._192.raw, usages, undefined, context( iterations, assert ) ); 47 | } ); 48 | 49 | QUnit.test( label + " key import/export raw 256 ", function( assert ) { 50 | ts.keyImportExportTest( aes.gcm._256.raw, usages, undefined, context( iterations, assert ) ); 51 | } ); 52 | 53 | QUnit.test( label + " key import/export jwk 128 ", function( assert ) { 54 | ts.keyImportExportTest( aes.gcm._128.jwk, undefined, undefined, context( iterations, assert ) ); 55 | } ); 56 | 57 | QUnit.test( label + " key import/export jwk 192 ", function( assert ) { 58 | ts.keyImportExportTest( aes.gcm._192.jwk, undefined, undefined, context( iterations, assert ) ); 59 | } ); 60 | 61 | QUnit.test( label + " key import/export jwk 256 ", function( assert ) { 62 | ts.keyImportExportTest( aes.gcm._256.jwk, undefined, undefined, context( iterations, assert ) ); 63 | } ); 64 | 65 | QUnit.test( label + " generateKeyTest 128", function( assert ) { 66 | ts.keyGenerateTest( aesGcmKeyAlg(128), usages, inspectAesGcmKey, context( iterations, assert ) ); 67 | } ); 68 | 69 | QUnit.test( label + " generateKeyTest 192", function( assert ) { 70 | ts.keyGenerateTest( aesGcmKeyAlg(192), usages, inspectAesGcmKey, context( iterations, assert ) ); 71 | } ); 72 | 73 | QUnit.test( label + " generateKeyTest 256", function( assert ) { 74 | ts.keyGenerateTest( aesGcmKeyAlg(256), usages, inspectAesGcmKey, context( iterations, assert ) ); 75 | } ); 76 | 77 | QUnit.test( label + " encrypt/decrypt 128", function( assert ) { 78 | ts.encryptDecryptTest( aesGcmKeyAlg(128), aesGcmEncryptAlg, context( iterations, assert ) ); 79 | } ); 80 | 81 | QUnit.test( label + " encrypt/decrypt 192", function( assert ) { 82 | ts.encryptDecryptTest( aesGcmKeyAlg(192), aesGcmEncryptAlg, context( iterations, assert ) ); 83 | } ); 84 | 85 | QUnit.test( label + " encrypt/decrypt 256", function( assert ) { 86 | ts.encryptDecryptTest( aesGcmKeyAlg(256), aesGcmEncryptAlg, context( iterations, assert ) ); 87 | } ); 88 | 89 | QUnit.test(label + " decrypt native ciphers 128", function(assert) { 90 | ts.decryptNativeCiphersTest(aes.gcm._128.ciphers, context(Math.min(aes.gcm._128.ciphers.vectors.length, iterations), assert)); 91 | }); 92 | 93 | QUnit.test(label + " decrypt native ciphers 192", function(assert) { 94 | ts.decryptNativeCiphersTest(aes.gcm._192.ciphers, context(Math.min(aes.gcm._192.ciphers.vectors.length, iterations), assert)); 95 | }); 96 | 97 | QUnit.test(label + " decrypt native ciphers 256", function(assert) { 98 | ts.decryptNativeCiphersTest(aes.gcm._256.ciphers, context(Math.min(aes.gcm._256.ciphers.vectors.length, iterations), assert)); 99 | }); 100 | 101 | } 102 | 103 | // AES-CBC specific key property validation 104 | function inspectAesGcmKey( keyObj, algorithm, usages, reason /* set reason.message to return fail messages */ ) { 105 | 106 | var fail = []; 107 | 108 | if ( !validation.prop.string( keyObj, "alg", "A" + algorithm.length + "GCM" ) ) { 109 | fail.push( "key.alg !== A" + algorithm.length + "GCM" ); 110 | } 111 | 112 | if ( !validation.prop.boolean( keyObj, "ext", true ) ) { 113 | fail.push( "key.ext !== true" ); 114 | } 115 | 116 | if ( !validation.prop.string( keyObj, "k", /^([A-Za-z0-9-_]+)$/ /* base64url */ ) ) { 117 | fail.push( "key.k not base64url" ); 118 | } 119 | 120 | // k property converts to bytes array of expected length 121 | var kBytes = msrCrypto.fromBase64( keyObj.k ); 122 | if ( !testShared.isBytes( kBytes, algorithm.length / 8 ) ) { 123 | fail.push( "key.k is not bytes" ); 124 | } 125 | 126 | // has key_ops property with expected usages 127 | if ( Object.prototype.toString.call( keyObj.key_ops ) !== "[object Array]" ) { 128 | fail.push( "key.key_ops missing or not Array" ); 129 | } 130 | 131 | if ( keyObj.key_ops && !testShared.compareUsages( keyObj.key_ops, usages ) ) { 132 | fail.push( "key.key_ops invalid usage(s)" ); 133 | } 134 | 135 | if ( !validation.prop.string( keyObj, "kty", "oct" ) ) { 136 | fail.push( "key.kty !== oct" ); 137 | } 138 | 139 | reason.message = fail.join( "; " ); 140 | 141 | return ( fail.length === 0 ); 142 | } 143 | 144 | // Generates a new encrypt/decrypt alg 145 | function aesGcmEncryptAlg( iteration ) { 146 | var tagLengths = [32, 64, 96, 104, 112, 120, 128]; 147 | var alg = { 148 | name: "AES-GCM", 149 | iv: testShared.arr( testShared.getRandomBytes( 12 ) ), 150 | tagLength: tagLengths[iteration % tagLengths.length] 151 | }; 152 | 153 | if ( testShared.chance( 0.5 ) ) { 154 | alg.additionalData = testShared.arr( testShared.getRandomBytes( 1, 100 ) ); 155 | } 156 | 157 | return alg; 158 | } 159 | 160 | function aesGcmKeyAlg( length ) { 161 | return { 162 | name: "AES-GCM", 163 | length: length 164 | }; 165 | } 166 | -------------------------------------------------------------------------------- /scripts/tests/Test.Aes.Kw.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | aesKWTests(); 22 | 23 | function aesKWTests() { 24 | 25 | QUnit.module( "AES-KW" ); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | var usages = [["wrapKey", "unwrapKey"], ["wrapKey"], ["unwrapKey"], ["unwrapKey", "wrapKey"]]; 30 | 31 | QUnit.test( label + " key import/export raw 128 ", function( assert ) { 32 | ts.keyImportExportTest( aes.kw._128.raw, usages, undefined, context( iterations, assert ) ); 33 | } ); 34 | 35 | QUnit.test( label + " key import/export raw 192 ", function( assert ) { 36 | ts.keyImportExportTest( aes.kw._192.raw, usages, undefined, context( iterations, assert ) ); 37 | } ); 38 | 39 | QUnit.test( label + " key import/export raw 256 ", function( assert ) { 40 | ts.keyImportExportTest( aes.kw._256.raw, usages, undefined, context( iterations, assert ) ); 41 | } ); 42 | 43 | QUnit.test( label + " key import/export jwk 128 ", function( assert ) { 44 | ts.keyImportExportTest( aes.kw._128.jwk, undefined, undefined, context( iterations, assert ) ); 45 | } ); 46 | 47 | QUnit.test( label + " key import/export jwk 192 ", function( assert ) { 48 | ts.keyImportExportTest( aes.kw._192.jwk, undefined, undefined, context( iterations, assert ) ); 49 | } ); 50 | 51 | QUnit.test( label + " key import/export jwk 256 ", function( assert ) { 52 | ts.keyImportExportTest( aes.kw._256.jwk, undefined, undefined, context( iterations, assert ) ); 53 | } ); 54 | 55 | QUnit.test( label + " generateKeyTest 128", function( assert ) { 56 | ts.keyGenerateTest( aesKWKeyAlg( 128 ), usages, inspectAesKWKey, context( iterations, assert ) ); 57 | } ); 58 | 59 | QUnit.test( label + " generateKeyTest 192", function( assert ) { 60 | ts.keyGenerateTest( aesKWKeyAlg( 192 ), usages, inspectAesKWKey, context( iterations, assert ) ); 61 | } ); 62 | 63 | QUnit.test( label + " generateKeyTest 256", function( assert ) { 64 | ts.keyGenerateTest( aesKWKeyAlg( 256 ), usages, inspectAesKWKey, context( iterations, assert ) ); 65 | } ); 66 | 67 | QUnit.test( label + " encrypt/decrypt 128", function( assert ) { 68 | ts.encryptDecryptTest( aesKWKeyAlg( 128 ), aesKWEncryptAlg, context( iterations, assert ) ); 69 | } ); 70 | 71 | QUnit.test( label + " encrypt/decrypt 192", function( assert ) { 72 | ts.encryptDecryptTest( aesKWKeyAlg( 192 ), aesKWEncryptAlg, context( iterations, assert ) ); 73 | } ); 74 | 75 | QUnit.test( label + " encrypt/decrypt 256", function( assert ) { 76 | ts.encryptDecryptTest( aesKWKeyAlg( 256 ), aesKWEncryptAlg, context( iterations, assert ) ); 77 | } ); 78 | 79 | QUnit.test(label + " decrypt native ciphers 128", function(assert) { 80 | ts.decryptNativeCiphersTest(aes.kw._128.ciphers, context(Math.min(aes.kw._128.ciphers.vectors.length, iterations), assert)); 81 | }); 82 | 83 | // QUnit.test(label + " decrypt native ciphers 192", function(assert) { 84 | // ts.decryptNativeCiphersTest(aes.kw._192.ciphers, context(Math.min(aes.kw._192.ciphers.vectors.length, iterations), assert)); 85 | // }); 86 | 87 | QUnit.test(label + " decrypt native ciphers 256", function(assert) { 88 | ts.decryptNativeCiphersTest(aes.kw._256.ciphers, context(Math.min(aes.kw._256.ciphers.vectors.length, iterations), assert)); 89 | }); 90 | 91 | } 92 | 93 | // AES-KW specific key property validation 94 | function inspectAesKWKey( keyObj, algorithm, usages, reason /* set reason.message to return fail messages */ ) { 95 | 96 | var fail = []; 97 | 98 | if ( !validation.prop.string( keyObj, "alg", "A" + algorithm.length + "KW" ) ) { 99 | fail.push( "key.alg !== A" + algorithm.length + "KW" ); 100 | } 101 | 102 | if ( !validation.prop.boolean( keyObj, "ext", true ) ) { 103 | fail.push( "key.ext !== true" ); 104 | } 105 | 106 | if ( !validation.prop.string( keyObj, "k", /^([A-Za-z0-9-_]+)$/ /* base64url */ ) ) { 107 | fail.push( "key.k not base64url" ); 108 | } 109 | 110 | // k property converts to bytes array of expected length 111 | var kBytes = msrCrypto.fromBase64( keyObj.k ); 112 | if ( !testShared.isBytes( kBytes, algorithm.length / 8 ) ) { 113 | fail.push( "key.k is not bytes" ); 114 | } 115 | 116 | // has key_ops property with expected usages 117 | if ( Object.prototype.toString.call( keyObj.key_ops ) !== "[object Array]" ) { 118 | fail.push( "key.key_ops missing or not Array" ); 119 | } 120 | 121 | if ( keyObj.key_ops && !testShared.compareUsages( keyObj.key_ops, usages ) ) { 122 | fail.push( "key.key_ops invalid usage(s)" ); 123 | } 124 | 125 | if ( !validation.prop.string( keyObj, "kty", "oct" ) ) { 126 | fail.push( "key.kty !== oct" ); 127 | } 128 | 129 | reason.message = fail.join( "; " ); 130 | 131 | return ( fail.length === 0 ); 132 | } 133 | 134 | // Generates a new encrypt/decrypt alg 135 | function aesKWEncryptAlg() { 136 | return { 137 | name: "AES-KW" 138 | }; 139 | } 140 | 141 | function aesKWKeyAlg( length ) { 142 | return { 143 | name: "AES-KW", 144 | length: length 145 | }; 146 | } 147 | -------------------------------------------------------------------------------- /scripts/tests/Test.ConcatKdf.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | concatTests(); 22 | 23 | function concatTests() { 24 | 25 | QUnit.module("CONCAT"); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | 30 | QUnit.test(label + " ts.deriveBitsTest Key --> bits ", function(assert) { 31 | var vectorSet = concat.DeriveBits; 32 | ts.deriveBitsTest(vectorSet, context(vectorSet.vectors.length, assert)); 33 | }); 34 | 35 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-128 ", function(assert) { 36 | var vectorSet = concat.aes.cbc._128.DeriveKey; 37 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 38 | }); 39 | 40 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-192 ", function(assert) { 41 | var vectorSet = concat.aes.cbc._192.DeriveKey; 42 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 43 | }); 44 | 45 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-256 ", function(assert) { 46 | var vectorSet = concat.aes.cbc._256.DeriveKey; 47 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 48 | }); 49 | 50 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-128 ", function(assert) { 51 | var vectorSet = concat.aes.gcm._128.DeriveKey; 52 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 53 | }); 54 | 55 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-192 ", function(assert) { 56 | var vectorSet = concat.aes.gcm._192.DeriveKey; 57 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 58 | }); 59 | 60 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-256 ", function(assert) { 61 | var vectorSet = concat.aes.gcm._256.DeriveKey; 62 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 63 | }); 64 | 65 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha1 ", function(assert) { 66 | var vectorSet = concat.hmac.sha1.DeriveKey; 67 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 68 | }); 69 | 70 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha256 ", function(assert) { 71 | var vectorSet = concat.hmac.sha256.DeriveKey; 72 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 73 | }); 74 | 75 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha384 ", function(assert) { 76 | var vectorSet = concat.hmac.sha384.DeriveKey; 77 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 78 | }); 79 | 80 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha512 ", function(assert) { 81 | var vectorSet = concat.hmac.sha512.DeriveKey; 82 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 83 | }); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /scripts/tests/Test.Encoding.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | QUnit.module( "Encoding" ); 20 | 21 | QUnit.test( "UTF-16 Surrogates to 4-byte UTF-8", function( assert) { 22 | 23 | // tslint:disable-next-line: max-line-length 24 | var fourByteUTF8 = "𠜎𠜱𠝹𠱓𠱸𠲖𠳏𠳕𠴕𠵼𠵿𠸎𠸏𠹷𠺝𠺢𠻗𠻹𠻺𠼭𠼮𠽌𠾴𠾼𠿪𡁜𡁯𡁵𡁶𡁻𡃁𡃉𡇙𢃇𢞵𢫕𢭃𢯊𢱑𢱕𢳂𢴈𢵌𢵧𢺳𣲷𤓓𤶸𤷪𥄫𦉘𦟌𦧲𦧺𧨾𨅝𨈇𨋢𨳊𨳍𨳒𩶘"; 25 | 26 | var bytes = msrCrypto.textToBytes(fourByteUTF8); 27 | 28 | var b64Text = msrCrypto.toBase64(bytes); 29 | 30 | var decodedBytes = msrCrypto.fromBase64(b64Text); 31 | 32 | var decodedString = msrCrypto.bytesToText(decodedBytes); 33 | 34 | if (fourByteUTF8.length !== decodedString.length) { 35 | assert.ok(false, "incorrect decoded length"); 36 | return; 37 | } 38 | 39 | assert.equal(fourByteUTF8, decodedString, "should be " + fourByteUTF8); 40 | 41 | } ); 42 | 43 | QUnit.test("3-byte UTF-8", function(assert) { 44 | 45 | // tslint:disable-next-line: max-line-length 46 | var threeByteUTF8 = "ሀሁሂሃሄህሆሇለሉሊላሌልሎሏሐሑሒሓሔሕሖሗመሙሚማሜምሞሟሠሡሢሣሤሥሦሧረሩሪራሬርሮሯሰሱሲሳሴስሶሷሸሹሺሻሼሽሾሿቀቁቂቃቄቅቆቇቈ቉ቊቋቌቍ቎቏ቐቑቒቓቔቕቖ቗ቘ቙ቚቛቜቝ቞቟በቡቢባቤብቦቧቨቩቪቫቬቭቮቯተቱቲታቴትቶቷቸቹቺቻቼችቾቿኀኁኂኃኄኅኆኇኈ኉ኊኋኌኍ኎኏ነኑኒናኔንኖኗኘኙኚኛኜኝኞኟአኡኢኣኤእኦኧከኩኪካኬክኮኯኰ኱ኲኳኴኵ኶኷ኸኹኺኻኼኽኾ኿ዀ዁ዂዃዄዅ዆዇ወዉዊዋዌውዎዏዐዑዒዓዔዕዖ዗ዘዙዚዛዜዝዞዟዠዡዢዣዤዥዦዧየዩዪያዬይዮዯደዱዲዳዴድዶዷዸዹዺዻዼዽዾዿጀጁጂጃጄጅጆጇገጉጊጋጌግጎጏጐ጑ጒጓጔጕ጖጗ጘጙጚጛጜጝጞጟጠጡጢጣጤጥጦጧጨጩጪጫጬጭጮጯጰጱጲጳጴጵጶጷጸጹጺጻጼጽጾጿፀፁፂፃፄፅፆፇፈፉፊፋፌፍፎፏፐፑፒፓፔፕፖፗፘፙፚ፛፜፝፞፟፠፡።፣፤፥፦፧፨፩፪፫፬፭፮፯፰፱፲፳፴፵፶፷፸፹፺፻፼፽፾፿ᎀᎁᎂᎃᎄᎅᎆᎇᎈᎉᎊᎋᎌᎍᎎᎏ᎐᎑᎒᎓᎔᎕᎖᎗᎘᎙᎚᎛᎜᎝᎞᎟ᎠᎡᎢᎣᎤᎥᎦᎧᎨᎩᎪᎫᎬᎭᎮᎯᎰᎱᎲᎳᎴᎵᎶᎷᎸᎹᎺᎻᎼᎽᎾᎿᏀᏁᏂᏃᏄᏅᏆᏇᏈᏉᏊᏋᏌᏍᏎᏏᏐᏑᏒᏓᏔᏕᏖᏗᏘᏙᏚᏛᏜᏝᏞᏟᏠᏡᏢᏣᏤᏥᏦᏧᏨᏩᏪᏫᏬᏭᏮᏯᏰᏱᏲᏳᏴᏵ᏶᏷ᏸᏹᏺᏻᏼᏽ᏾᏿᐀ᐁᐂᐃᐄᐅᐆᐇᐈᐉᐊᐋᐌᐍᐎᐏᐐᐑᐒᐓᐔᐕᐖᐗᐘᐙᐚᐛᐜᐝᐞᐟᐠᐡᐢᐣᐤᐥᐦᐧᐨᐩᐪᐫᐬᐭᐮᐯᐰᐱᐲᐳᐴᐵᐶᐷᐸᐹᐺᐻᐼᐽᐾᐿᑀᑁᑂᑃᑄᑅᑆᑇᑈᑉᑊᑋᑌᑍᑎᑏᑐᑑᑒᑓᑔᑕᑖᑗᑘᑙᑚᑛᑜᑝᑞᑟᑠᑡᑢᑣᑤᑥᑦᑧᑨᑩᑪᑫᑬᑭᑮᑯᑰᑱᑲᑳᑴᑵᑶᑷᑸᑹᑺᑻᑼᑽᑾᑿᒀᒁᒂᒃᒄᒅᒆᒇᒈᒉᒊᒋᒌᒍᒎᒏᒐᒑᒒᒓᒔᒕᒖᒗᒘᒙᒚᒛᒜᒝᒞᒟᒠᒡᒢᒣᒤᒥᒦᒧᒨᒩᒪᒫᒬᒭᒮᒯᒰᒱᒲᒳᒴᒵᒶᒷᒸᒹᒺᒻᒼᒽᒾᒿᓀᓁᓂᓃᓄᓅᓆᓇᓈᓉᓊᓋᓌᓍᓎᓏᓐᓑᓒᓓᓔᓕᓖᓗᓘᓙᓚᓛᓜᓝᓞᓟᓠᓡᓢᓣᓤᓥᓦᓧᓨᓩᓪᓫᓬᓭᓮᓯᓰᓱᓲᓳᓴᓵᓶᓷᓸᓹᓺᓻᓼᓽᓾᓿᔀᔁᔂᔃᔄᔅᔆᔇᔈᔉᔊᔋᔌᔍᔎᔏᔐᔑᔒᔓᔔᔕᔖᔗᔘᔙᔚᔛᔜᔝᔞᔟᔠᔡᔢᔣᔤᔥᔦᔧᔨᔩᔪᔫᔬᔭᔮᔯᔰᔱᔲᔳᔴᔵᔶᔷᔸᔹᔺᔻᔼᔽᔾᔿᕀᕁᕂᕃᕄᕅᕆᕇᕈᕉᕊᕋᕌᕍᕎᕏᕐᕑᕒᕓᕔᕕᕖᕗᕘᕙᕚᕛᕜᕝᕞᕟᕠᕡᕢᕣᕤᕥᕦᕧᕨᕩᕪᕫᕬᕭᕮᕯᕰᕱᕲᕳᕴᕵᕶᕷᕸᕹᕺᕻᕼᕽᕾᕿᖀᖁᖂᖃᖄᖅᖆᖇᖈᖉᖊᖋᖌᖍᖎᖏᖐᖑᖒᖓᖔᖕᖖᖗᖘᖙᖚᖛᖜᖝᖞᖟᖠᖡᖢᖣᖤᖥᖦᖧᖨᖩᖪᖫᖬᖭᖮᖯᖰᖱᖲᖳᖴᖵᖶᖷᖸᖹᖺᖻᖼᖽᖾᖿᗀᗁᗂᗃᗄᗅᗆᗇᗈᗉᗊᗋᗌᗍᗎᗏᗐᗑᗒᗓᗔᗕᗖᗗᗘᗙᗚᗛᗜᗝᗞᗟᗠᗡᗢᗣᗤᗥᗦᗧᗨᗩᗪᗫᗬᗭᗮᗯᗰᗱᗲᗳᗴᗵᗶᗷᗸᗹᗺᗻᗼᗽᗾᗿᘀᘁᘂᘃᘄᘅᘆᘇᘈᘉᘊᘋᘌᘍᘎᘏᘐᘑᘒᘓᘔᘕᘖᘗᘘᘙᘚᘛᘜᘝᘞᘟᘠᘡᘢᘣᘤᘥᘦᘧᘨᘩᘪᘫᘬᘭᘮᘯᘰᘱᘲᘳᘴᘵᘶᘷᘸᘹᘺᘻᘼᘽᘾᘿᙀᙁᙂᙃᙄᙅᙆᙇᙈᙉᙊᙋᙌᙍᙎᙏᙐᙑᙒᙓᙔᙕᙖᙗᙘᙙᙚᙛᙜᙝᙞᙟᙠᙡᙢᙣᙤᙥᙦᙧᙨᙩᙪᙫᙬ᙭᙮ᙯᙰᙱᙲᙳᙴᙵᙶᙷᙸᙹᙺᙻᙼᙽᙾᙿ ᚁᚂᚃᚄᚅᚆᚇᚈᚉᚊᚋᚌᚍᚎᚏᚐᚑᚒᚓᚔᚕᚖᚗᚘᚙᚚ᚛᚜᚝᚞᚟ᚠᚡᚢᚣᚤᚥᚦᚧᚨᚩᚪᚫᚬᚭᚮᚯᚰᚱᚲᚳᚴᚵᚶᚷᚸᚹᚺᚻᚼᚽᚾᚿᛀᛁᛂᛃᛄᛅᛆᛇᛈᛉᛊᛋᛌᛍᛎᛏᛐᛑᛒᛓᛔᛕᛖᛗᛘᛙᛚᛛᛜᛝᛞᛟᛠᛡᛢᛣᛤᛥᛦᛧᛨᛩᛪ᛫᛬᛭ᛮᛯᛰᛱᛲᛳᛴᛵᛶᛷᛸ᛹᛺᛻᛼᛽᛾᛿ᜀᜁᜂᜃᜄᜅᜆᜇᜈᜉᜊᜋᜌᜍᜎᜏᜐᜑᜒᜓ᜔᜕᜖᜗᜘᜙᜚᜛᜜᜝᜞ᜟᜠᜡᜢᜣᜤᜥᜦᜧᜨᜩᜪᜫᜬᜭᜮᜯᜰᜱᜲᜳ᜴᜵᜶᜷᜸᜹᜺᜻᜼᜽᜾᜿ᝀᝁᝂᝃᝄᝅᝆᝇᝈᝉᝊᝋᝌᝍᝎᝏᝐᝑᝒᝓ᝔᝕᝖᝗᝘᝙᝚᝛᝜᝝᝞᝟ᝠᝡᝢᝣᝤᝥᝦᝧᝨᝩᝪᝫᝬ᝭ᝮᝯᝰ᝱ᝲᝳ᝴᝵᝶᝷᝸᝹᝺᝻᝼᝽᝾᝿"; 47 | 48 | var bytes = msrCrypto.textToBytes(threeByteUTF8); 49 | 50 | var b64Text = msrCrypto.toBase64(bytes); 51 | 52 | var decodedBytes = msrCrypto.fromBase64(b64Text); 53 | 54 | var decodedString = msrCrypto.bytesToText(decodedBytes); 55 | 56 | if (threeByteUTF8.length !== decodedString.length) { 57 | assert.ok(false, "incorrect decoded length"); 58 | return; 59 | } 60 | 61 | assert.equal(threeByteUTF8, decodedString, "should be " + threeByteUTF8); 62 | 63 | } ); 64 | -------------------------------------------------------------------------------- /scripts/tests/Test.Hkdf.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | hkdfTests(); 22 | 23 | function hkdfTests() { 24 | 25 | QUnit.module("HKDF"); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | 30 | QUnit.test(label + " ts.deriveBitsTest KeyData --> bits ", function(assert) { 31 | var vectorSet = hkdf.DeriveBits; 32 | ts.deriveBitsTest(vectorSet, context(vectorSet.vectors.length, assert)); 33 | }); 34 | 35 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-128 ", function(assert) { 36 | var vectorSet = hkdf.aes.gcm._128.DeriveKey; 37 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 38 | }); 39 | 40 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-256 ", function(assert) { 41 | var vectorSet = hkdf.aes.gcm._256.DeriveKey; 42 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 43 | }); 44 | 45 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-128 ", function(assert) { 46 | var vectorSet = hkdf.aes.cbc._128.DeriveKey; 47 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 48 | }); 49 | 50 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-256 ", function(assert) { 51 | var vectorSet = hkdf.aes.cbc._256.DeriveKey; 52 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 53 | }); 54 | 55 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha1 ", function(assert) { 56 | var vectorSet = hkdf.hmac.sha1.DeriveKey; 57 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 58 | }); 59 | 60 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha256 ", function(assert) { 61 | var vectorSet = hkdf.hmac.sha256.DeriveKey; 62 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 63 | }); 64 | 65 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha384 ", function(assert) { 66 | var vectorSet = hkdf.hmac.sha384.DeriveKey; 67 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 68 | }); 69 | 70 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha512 ", function(assert) { 71 | var vectorSet = hkdf.hmac.sha512.DeriveKey; 72 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 73 | }); 74 | 75 | } 76 | -------------------------------------------------------------------------------- /scripts/tests/Test.HkdfCtr.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | hkdfCtrTests(); 22 | 23 | function hkdfCtrTests() { 24 | 25 | QUnit.module("HKDF-CTR"); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | 30 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-128 ", function(assert) { 31 | var vectorSet = hkdfctr.aes.cbc._128.DeriveKey; 32 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 33 | }); 34 | 35 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-192 ", function(assert) { 36 | var vectorSet = hkdfctr.aes.cbc._192.DeriveKey; 37 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 38 | }); 39 | 40 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Cbc-256 ", function(assert) { 41 | var vectorSet = hkdfctr.aes.cbc._256.DeriveKey; 42 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 43 | }); 44 | 45 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-128 ", function(assert) { 46 | var vectorSet = hkdfctr.aes.gcm._128.DeriveKey; 47 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 48 | }); 49 | 50 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-192 ", function(assert) { 51 | var vectorSet = hkdfctr.aes.gcm._192.DeriveKey; 52 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 53 | }); 54 | 55 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Aes-Gcm-256 ", function(assert) { 56 | var vectorSet = hkdfctr.aes.gcm._256.DeriveKey; 57 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 58 | }); 59 | 60 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha1 ", function(assert) { 61 | var vectorSet = hkdfctr.hmac.sha1.DeriveKey; 62 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 63 | }); 64 | 65 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha256 ", function(assert) { 66 | var vectorSet = hkdfctr.hmac.sha256.DeriveKey; 67 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 68 | }); 69 | 70 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha384 ", function(assert) { 71 | var vectorSet = hkdfctr.hmac.sha384.DeriveKey; 72 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 73 | }); 74 | 75 | QUnit.test(label + " ts.deriveKeyTest KeyData --> Hmac-Sha512 ", function(assert) { 76 | var vectorSet = hkdfctr.hmac.sha512.DeriveKey; 77 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 78 | }); 79 | 80 | QUnit.test(label + " ts.deriveBitsTest Key --> bits ", function(assert) { 81 | var vectorSet = hkdfctr.DeriveBits; 82 | ts.deriveBitsTest(vectorSet, context(vectorSet.vectors.length, assert)); 83 | }); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /scripts/tests/Test.Hmac.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | hmacTests(); 22 | 23 | function hmacTests() { 24 | 25 | QUnit.module( "HMAC" ); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | var hmacUsages = [[VERIFY, SIGN], [SIGN], [VERIFY], [SIGN, VERIFY]]; 30 | 31 | QUnit.test( label + " generateKeyTest SHA-1", function( assert ) { 32 | ts.keyGenerateTest( hmacKeyAlg( "SHA-1" ), hmacUsages, inspectHmacKey, context( iterations, assert ) ); 33 | } ); 34 | 35 | QUnit.test( label + " generateKeyTest SHA-256", function( assert ) { 36 | ts.keyGenerateTest( hmacKeyAlg( "SHA-256" ), hmacUsages, inspectHmacKey, context( iterations, assert ) ); 37 | } ); 38 | 39 | QUnit.test( label + " generateKeyTest SHA-384", function( assert ) { 40 | ts.keyGenerateTest( hmacKeyAlg( "SHA-384" ), hmacUsages, inspectHmacKey, context( iterations, assert ) ); 41 | } ); 42 | 43 | QUnit.test( label + " generateKeyTest SHA-512", function( assert ) { 44 | ts.keyGenerateTest( hmacKeyAlg( "SHA-512" ), hmacUsages, inspectHmacKey, context( iterations, assert ) ); 45 | } ); 46 | 47 | QUnit.test( label + " verify native signature SHA-1 ", function( assert ) { 48 | ts.verifyNativeSignatureTest( 49 | hmacKeyAlg( "SHA-1" ), hmac.sign_verify.sha1, context( iterations, assert ) ); 50 | } ); 51 | 52 | QUnit.test( label + " verify native signature SHA-256 ", function( assert ) { 53 | ts.verifyNativeSignatureTest( 54 | hmacKeyAlg( "SHA-256" ), hmac.sign_verify.sha256, context( iterations, assert ) ); 55 | } ); 56 | 57 | QUnit.test( label + " verify native signature SHA-384 ", function( assert ) { 58 | ts.verifyNativeSignatureTest( 59 | hmacKeyAlg( "SHA-384" ), hmac.sign_verify.sha384, context( iterations, assert ) ); 60 | } ); 61 | 62 | QUnit.test( label + " verify native signature SHA-512 ", function( assert ) { 63 | ts.verifyNativeSignatureTest( 64 | hmacKeyAlg( "SHA-512" ), hmac.sign_verify.sha512, context( iterations, assert ) ); 65 | } ); 66 | 67 | // =========================================================================================================== 68 | 69 | QUnit.test( label + " sign/verify SHA-1", function( assert ) { 70 | ts.signVerifyTest( hmacKeyAlg( "SHA-1" ), {name: "HMAC"}, context( iterations, assert ) ); 71 | } ); 72 | 73 | QUnit.test( label + " sign/verify SHA-256", function( assert ) { 74 | ts.signVerifyTest( hmacKeyAlg( "SHA-256" ), { name: "HMAC" }, context( iterations, assert ) ); 75 | } ); 76 | 77 | QUnit.test( label + " sign/verify SHA-384", function( assert ) { 78 | ts.signVerifyTest( hmacKeyAlg( "SHA-384" ), { name: "HMAC" }, context( iterations, assert ) ); 79 | } ); 80 | 81 | QUnit.test( label + " sign/verify SHA-512", function( assert ) { 82 | ts.signVerifyTest( hmacKeyAlg( "SHA-512" ), { name: "HMAC" }, context( iterations, assert ) ); 83 | } ); 84 | 85 | // =========================================================================================================== 86 | 87 | QUnit.test( label + " key import/export jwk SHA-1 ", function( assert ) { 88 | ts.keyImportExportTest( 89 | hmac.sha1.jwk, undefined, undefined, context( iterations, assert ) ); 90 | } ); 91 | 92 | QUnit.test( label + " key import/export jwk SHA-256 ", function( assert ) { 93 | ts.keyImportExportTest( 94 | hmac.sha256.jwk, undefined, undefined, context( iterations, assert ) ); 95 | } ); 96 | 97 | QUnit.test( label + " key import/export jwk SHA-384 ", function( assert ) { 98 | ts.keyImportExportTest( 99 | hmac.sha384.jwk, undefined, undefined, context( iterations, assert ) ); 100 | } ); 101 | 102 | QUnit.test( label + " key import/export jwk SHA-512 ", function( assert ) { 103 | ts.keyImportExportTest( 104 | hmac.sha512.jwk, undefined, undefined, context( iterations, assert ) ); 105 | } ); 106 | } 107 | 108 | // function hmacKeyValidateJwk( actualKey, expectedKey ) { 109 | 110 | // // key_ops usages may not be in the same order and will fail the deepEquals check 111 | // // we'll verify they have the same items. Then set them to be the same before deepEquals 112 | // if ( compareUsages( actualKey.key_ops, expectedKey.key_ops ) === false ) { 113 | // QUnit.assert.ok( false, "usages do not match." ); 114 | // return false; 115 | // } 116 | // expectedKey.key_ops = actualKey.key_ops.slice(); 117 | 118 | // QUnit.assert.deepEqual( actualKey, expectedKey, JSON.stringify( expectedKey ) ); 119 | // } 120 | 121 | // function hmacKeyValidateRaw( actualKey, expectedKey ) { 122 | // QUnit.assert.deepEqual( toArray( actualKey ), toArray( expectedKey ), JSON.stringify( expectedKey ) ); 123 | // } 124 | 125 | function hmacKeyAlg( hashAlg ) { 126 | return { 127 | name: "HMAC", 128 | hash: { name: hashAlg } 129 | }; 130 | } 131 | 132 | var inspectHmacKey = function( keyObj, algorithm, usages, reason /* set reason.message to return fail messages */ ) { 133 | 134 | // { 135 | // kty: "oct", 136 | // k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE", 137 | // alg: "HS256", 138 | // ext: true, 139 | // } 140 | 141 | var fail = []; 142 | 143 | var algNames = { "SHA-1": "HS1", "SHA-256": "HS256", "SHA-384": "HS384", "SHA-512": "HS512" }; 144 | var keyLengths = { "SHA-1": 64, "SHA-224": 64, "SHA-256": 64, "SHA-384": 128, "SHA-512": 128 }; 145 | 146 | var expLenMax = keyLengths[algorithm.hash.name]; 147 | var expLenMin = expLenMax - 0; 148 | 149 | // has kty property equal to 'oct' 150 | if ( !validation.prop.string( keyObj, "alg", algNames[algorithm.hash.name] ) ) { 151 | fail.push( "key.kty !== " + algNames[algorithm.hash.name] ); 152 | } 153 | 154 | // has ext property equal to true 155 | if ( !validation.prop.boolean( keyObj, "ext", true ) ) { 156 | fail.push( "key.ext !== true" ); 157 | } 158 | 159 | // has e property that is base64url 160 | if ( !validation.prop.isBase64Url( keyObj, "k", expLenMin, expLenMax ) ) { 161 | fail.push( "key.k is not base64url or has incorrect length" ); 162 | } 163 | 164 | // has key_ops property with expected usages 165 | if ( Object.prototype.toString.call( keyObj.key_ops ) !== "[object Array]" ) { 166 | fail.push( "key.key_ops missing or not Array" ); 167 | } 168 | 169 | if ( keyObj.key_ops && !testShared.compareUsages( keyObj.key_ops, usages ) ) { 170 | fail.push( "key.key_ops invalid usage(s)" ); 171 | } 172 | 173 | // has kty property equal to 'oct' 174 | if ( !validation.prop.string( keyObj, "kty", "oct" ) ) { 175 | fail.push( "key.kty !== oct" ); 176 | } 177 | 178 | reason.message = fail.join( "; " ); 179 | 180 | return ( fail.length === 0 ); 181 | 182 | }; 183 | -------------------------------------------------------------------------------- /scripts/tests/Test.Pbkdf2.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | pbkdf2Tests(); 22 | 23 | function pbkdf2Tests() { 24 | 25 | QUnit.module("PBKDF2"); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | 30 | QUnit.test(label + " ts.deriveBitsTest Password --> bits ", function(assert) { 31 | var vectorSet = pbkdf2.DeriveBits; 32 | ts.deriveBitsTest(vectorSet, context(vectorSet.vectors.length, assert)); 33 | }); 34 | 35 | QUnit.test(label + " ts.deriveKeyTest Password --> Aes-Gcm-128 ", function(assert) { 36 | var vectorSet = pbkdf2.aes.gcm._128.DeriveKey; 37 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 38 | }); 39 | 40 | QUnit.test(label + " ts.deriveKeyTest Password --> Aes-Gcm-256 ", function(assert) { 41 | var vectorSet = pbkdf2.aes.gcm._256.DeriveKey; 42 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 43 | }); 44 | 45 | QUnit.test(label + " ts.deriveKeyTest Password --> Aes-Cbc-128 ", function(assert) { 46 | var vectorSet = pbkdf2.aes.cbc._128.DeriveKey; 47 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 48 | }); 49 | 50 | QUnit.test(label + " ts.deriveKeyTest Password --> Aes-Cbc-256 ", function(assert) { 51 | var vectorSet = pbkdf2.aes.cbc._256.DeriveKey; 52 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 53 | }); 54 | 55 | QUnit.test(label + " ts.deriveKeyTest Password --> Hmac-Sha1 ", function(assert) { 56 | var vectorSet = pbkdf2.hmac.sha1.DeriveKey; 57 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 58 | }); 59 | 60 | QUnit.test(label + " ts.deriveKeyTest Password --> Hmac-Sha256 ", function(assert) { 61 | var vectorSet = pbkdf2.hmac.sha256.DeriveKey; 62 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 63 | }); 64 | 65 | QUnit.test(label + " ts.deriveKeyTest Password --> Hmac-Sha384 ", function(assert) { 66 | var vectorSet = pbkdf2.hmac.sha384.DeriveKey; 67 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 68 | }); 69 | 70 | QUnit.test(label + " ts.deriveKeyTest Password --> Hmac-Sha512 ", function(assert) { 71 | var vectorSet = pbkdf2.hmac.sha512.DeriveKey; 72 | ts.deriveKeyTest(vectorSet, undefined, context(vectorSet.vectors.length, assert)); 73 | }); 74 | 75 | } 76 | -------------------------------------------------------------------------------- /scripts/tests/Test.Prng.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | // These Known Answer Tests (KAT) are taken from Windows CNG FIPS 140-2 verification effort, 20 | // which was provided by Windows CNG FIPS certification lab (CMVP) for AES-256 no derivation function. 21 | 22 | test("PRNG vectors", function() { 23 | var numberOfTests = 0, i; 24 | testVectors = prngKAT; 25 | for (i = 0; i < testVectors.length; i++) { 26 | numberOfTests += testVectors[i].expected.length; 27 | } 28 | 29 | // Q-unit uses the Expect() function to declare how many test assertions 30 | // you expect to have. So if some bug quietly kills a function, q-unit 31 | // will let you know that the expected number of asserts wasn't evaluated 32 | expect(numberOfTests); 33 | 34 | for (i = 0; i < testVectors.length; i++) { 35 | 36 | var seed = testVectors[i].seed; 37 | var personalizationString = testVectors[i].personalizationString; 38 | var additionalInputArray = testVectors[i].additionalInput; 39 | var expectedArray = testVectors[i].expected; 40 | var randomBytes; 41 | 42 | msrcryptoPseudoRandom.init(seed, personalizationString); 43 | 44 | for (var j = 0; j < expectedArray.length; j++) { 45 | var expectedBytes = expectedArray[j]; 46 | var additionalInput = additionalInputArray[j]; 47 | var bytesToGet = expectedBytes.length; 48 | randomBytes = msrcryptoPseudoRandom.getBytes(bytesToGet, additionalInput); 49 | 50 | // Q-unit equal assertion. Passes if 1st param equals 2nd param. 51 | // Using join() here to convert arrays to strings for comparison 52 | equal(randomBytes.join(), expectedBytes.join(), 53 | "Passed - Seed " + i.toString() + " Generate " + j.toString()); 54 | } 55 | } 56 | }); 57 | 58 | test("PRNG init", function() { 59 | var numberOfTests = 32; 60 | expect(numberOfTests); 61 | var entropy = prngKAT[0].seed.slice(0); 62 | var randomNumberLength = 128; 63 | 64 | // Initialize 65 | msrcryptoPseudoRandom.init(entropy); 66 | 67 | // Reseed multiple times, and ask for random numbers. 68 | for (var i = 0; i < numberOfTests; ++i) { 69 | msrcryptoPseudoRandom.reseed(entropy); 70 | msrcryptoPseudoRandom.reseed(entropy); 71 | msrcryptoPseudoRandom.reseed(entropy); 72 | msrcryptoPseudoRandom.reseed(entropy); 73 | entropy = msrcryptoPseudoRandom.getBytes(randomNumberLength); 74 | ok(true, "PRNG Init/getBytes passed [" + i.toString() + "]"); 75 | } 76 | }); 77 | -------------------------------------------------------------------------------- /scripts/tests/Test.Sha2.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | 19 | "use strict"; 20 | 21 | hashTests(); 22 | 23 | function hashTests() { 24 | 25 | QUnit.module( "SHA2" ); 26 | 27 | var ts = testShared; 28 | var context = ts.testContext; 29 | 30 | QUnit.test( label + " vectors SHA-1", function( assert ) { 31 | ts.hashTest( sha2.sha1, context( sha2.sha1.vectors.length, assert ) ); 32 | } ); 33 | 34 | QUnit.test( label + " vectors SHA-224", function( assert ) { 35 | ts.hashTest( sha2.sha224, context( sha2.sha224.vectors.length, assert ) ); 36 | } ); 37 | 38 | QUnit.test( label + " vectors SHA-256", function( assert ) { 39 | ts.hashTest( sha2.sha256, context( sha2.sha256.vectors.length, assert ) ); 40 | } ); 41 | 42 | QUnit.test( label + " vectors SHA-384", function( assert ) { 43 | ts.hashTest( sha2.sha384, context( sha2.sha384.vectors.length, assert ) ); 44 | } ); 45 | 46 | QUnit.test( label + " vectors SHA-512", function( assert ) { 47 | ts.hashTest( sha2.sha512, context( sha2.sha512.vectors.length, assert ) ); 48 | } ); 49 | } 50 | -------------------------------------------------------------------------------- /scripts/worker.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | 3 | // 4 | // Copyright 2020 Microsoft 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | // 18 | //******************************************************************************* 19 | 20 | var msrcryptoWorker = (function() { 21 | 22 | // If we're running in a webworker we need to postMessage to return our result 23 | // otherwise just return the value as normal. 24 | function returnResult(result) { 25 | 26 | if (workerInitialized && runningInWorkerInstance) { 27 | self.postMessage(result); 28 | } 29 | return result; 30 | } 31 | 32 | var workerId, 33 | operationType, 34 | operationSubType; 35 | 36 | return { 37 | 38 | jsCryptoRunner: function(e) { 39 | 40 | workerId = e.data.workerid; 41 | operationType = e.data.operationType; 42 | operationSubType = e.data.operationSubType; 43 | 44 | var operation = e.data.operationType, 45 | result, 46 | func = operations[operation][e.data.algorithm.name], 47 | p = e.data; 48 | 49 | if (!operations.exists(operation, e.data.algorithm.name)) { 50 | throw new Error("unregistered algorithm."); 51 | } 52 | 53 | if (p.operationSubType) { 54 | result = returnResult({ type: p.operationSubType, result: func(p) }); 55 | } else { 56 | result = returnResult(func(p)); 57 | } 58 | 59 | return result; 60 | }, 61 | 62 | returnResult: returnResult 63 | }; 64 | 65 | })(); 66 | 67 | // If this is running in a webworker we need self.onmessage to receive messages from 68 | // the calling script. 69 | // If we are in 'synchronous mode' (everything running in one script) 70 | // we don't want to override self.onmessage. 71 | // We could be running in a webworker as a main script (not a child script) 72 | // so we will ignore messages if we've not been initialized. 73 | if (runningInWorkerInstance) { 74 | 75 | self.onmessage = function(/*@type(typeEvent)*/e) { 76 | 77 | // When this worker first gets instantiated we will receive seed data 78 | // for this workers prng. 79 | if (!workerInitialized && e.data.prngSeed) { 80 | var entropy = e.data.prngSeed; 81 | msrcryptoPseudoRandom.init(entropy); 82 | workerInitialized = true; 83 | return msrcryptoWorker.returnResult({ initialized: true }); 84 | } 85 | 86 | // Process the crypto operation 87 | if (workerInitialized === true) { msrcryptoWorker.jsCryptoRunner(e); } 88 | 89 | }; 90 | } 91 | -------------------------------------------------------------------------------- /scripts/wrapKey.js: -------------------------------------------------------------------------------- 1 | //******************************************************************************* 2 | // 3 | // Copyright 2020 Microsoft 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | // 17 | //******************************************************************************* 18 | var msrcryptoWrapKey = (function() { 19 | 20 | var utils = msrcryptoUtilities; 21 | 22 | function wrapKey(params) { 23 | 24 | var rsaObj = msrcryptoRsa( 25 | params.keyData1, 26 | params.keyHandle1.algorithm.name, 27 | msrcryptoHashFunctions["SHA-1"])(); 28 | 29 | var tagLength = 128; 30 | 31 | var keyToWrapJwk = msrcryptoJwk.keyToJwkOld(params.keyHandle, params.keyData); 32 | 33 | var jweHeader = { 34 | "alg": params.keyHandle1.algorithm.name.toUpperCase(), 35 | "enc": "A128GCM" 36 | }; 37 | 38 | var encodedJweHeader = 39 | utils.toBase64(JSON.stringify(jweHeader), true); 40 | 41 | var cmk = msrcryptoPseudoRandom.getBytes(32); 42 | 43 | var jweEncryptedKey = rsaObj.encrypt(cmk); 44 | 45 | var encodedJweEncryptedKey = utils.toBase64(jweEncryptedKey, true); 46 | 47 | var jweIv = msrcryptoPseudoRandom.getBytes(12); 48 | 49 | var encodedJweIv = utils.toBase64(jweIv, true); 50 | 51 | var additionalData = encodedJweHeader.concat(".", encodedJweEncryptedKey, ".", encodedJweIv); 52 | 53 | var gcm = msrcryptoGcm(msrcryptoBlockCipher.aes(cmk)); 54 | gcm.init(jweIv, utils.stringToBytes(additionalData), tagLength); 55 | 56 | var ciphertextPlusTag = gcm.encrypt(keyToWrapJwk); 57 | 58 | var tag = ciphertextPlusTag.slice(-(tagLength / 8)); 59 | 60 | var encodedIntegrityValue = utils.toBase64(tag, true); 61 | 62 | var encodedCiphertext = 63 | utils.toBase64(ciphertextPlusTag.slice(0, ciphertextPlusTag.length - tag.length), true); 64 | 65 | var jwe = { 66 | 67 | recipients: [{ 68 | header: encodedJweHeader, 69 | encrypted_key: encodedJweEncryptedKey, 70 | integrity_value: encodedIntegrityValue 71 | } 72 | ], 73 | initialization_vector: encodedJweIv, 74 | ciphertext: encodedCiphertext 75 | 76 | }; 77 | 78 | return utils.stringToBytes(JSON.stringify(jwe)); 79 | 80 | } 81 | 82 | function unwrapKey(params) { 83 | 84 | var b64Tobytes = utils.fromBase64; 85 | 86 | var keyDataJwk = 87 | JSON.parse(String.fromCharCode.apply(null, params.buffer)); 88 | 89 | var header = utils.fromBase64(keyDataJwk.recipients[0].header); 90 | 91 | // tslint:disable-next-line: variable-name 92 | var encrypted_key = 93 | b64Tobytes(keyDataJwk.recipients[0].encrypted_key); 94 | 95 | // tslint:disable-next-line: variable-name 96 | var integrity_value = 97 | b64Tobytes(keyDataJwk.recipients[0].integrity_value); 98 | 99 | // tslint:disable-next-line: variable-name 100 | var initialization_vector = 101 | b64Tobytes(keyDataJwk.initialization_vector); 102 | 103 | var ciphertext = 104 | b64Tobytes(keyDataJwk.ciphertext); 105 | 106 | var hashFunc = msrcryptoHashFunctions["SHA-1"](); 107 | var rsaObj = msrcryptoRsa(params.keyData, params.keyHandle.algorithm.name, hashFunc); 108 | var inKey = rsaObj.decrypt(encrypted_key); 109 | 110 | var additionalData = 111 | keyDataJwk.recipients[0].header.concat(".", keyDataJwk.recipients[0].encrypted_key, ".", 112 | keyDataJwk.initialization_vector); 113 | 114 | var gcm = msrcryptoGcm(msrcryptoBlockCipher.aes(inKey)); 115 | gcm.init(initialization_vector, utils.stringToBytes(additionalData), 128); 116 | 117 | var result = gcm.decrypt(ciphertext, integrity_value); 118 | 119 | var keyObject = msrcryptoJwk.jwkToKey(result, params.algorithm, ["k"]); 120 | 121 | return { 122 | type: "keyImport", 123 | keyData: keyObject.k, 124 | keyHandle: { 125 | algorithm: { name: params.algorithm.name }, 126 | extractable: params.extractable || keyObject.extractable, 127 | usages: params.usages, 128 | type: "secret" 129 | } 130 | }; 131 | } 132 | return { 133 | wrapKey: wrapKey, 134 | unwrapKey: unwrapKey 135 | 136 | }; 137 | 138 | })(); 139 | if (typeof operations !== "undefined") { 140 | operations.register("wrapKey", "AES-GCM", msrcryptoWrapKey.wrapKey); 141 | operations.register("unwrapKey", "AES-CBC", msrcryptoWrapKey.unwrapKey); 142 | } 143 | -------------------------------------------------------------------------------- /tests/CryptoECCTests.html: -------------------------------------------------------------------------------- 1 |  20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Crypto ECC Tests 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /tests/CryptoMathTests.html: -------------------------------------------------------------------------------- 1 |  20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Crypto Math Tests 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /tests/SubtleTests.html: -------------------------------------------------------------------------------- 1 |  20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Subtle Tests 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | --------------------------------------------------------------------------------