remove old files

This commit is contained in:
themighty1
2021-11-21 17:34:34 +03:00
parent 4e125731fd
commit 7163ed4c90
170 changed files with 0 additions and 63012 deletions

View File

@@ -1,8 +0,0 @@
var link1 = document.getElementById("link1");
link1.addEventListener("click", function(evt) {
sendMessage({
'destination': 'extension',
'message': 'openLink1'
});
window.close();
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 B

View File

@@ -1,19 +0,0 @@
<html>
<head>
</head>
<body>
<script type="module" src="pkijs/pagesigner_imports.js"></script>
<!-- <script src="snarkjs/snarkjs.js"></script>
<script src="snarkjs/buffer.js"></script> -->
<script src="socket.js"></script>
<script src="tlsn_utils.js"></script>
<script src="indexeddb.js"></script>
<script src="oracles.js"></script>
<script src="pako.js"></script>
<script src="tlsn.js"></script>
<script src="testing/testing.js"></script>
<script src="verifychain/verifychain.js"></script>
<script src="globals.js"></script>
<script src="main.js"></script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,72 +0,0 @@
//Because file picker doesn't work from popup.html we open a new tab just for this purpose
var is_chrome = window.navigator.userAgent.match('Chrome') ? true : false;
var is_file_picker = false; //toggled to true when invoked as a file picker
function prepare_testing(){
var script = document.createElement('script');
script.src = 'testing/file_picker_test.js';
document.body.appendChild(script);
}
//triggered by exrension
function showFilePicker(){
is_file_picker = true
var label = document.getElementById("import_label");
label.style.display = "";
var fileChooser = document.getElementById("import");
fileChooser.addEventListener('change', function(evt) {
var f = evt.target.files[0];
if (f) {
var reader = new FileReader();
reader.onload = onload;
reader.readAsArrayBuffer(f);
}
});
}
function onload(e) {
var loader = document.getElementById("loader");
loader.classList.toggle("m-fadeIn");
loader.removeAttribute('hidden');
var import_label = document.getElementById("import_label");
//import_label.style.display = 'none'
import_label.classList.toggle("m-fadeOut");
var contents = e.target.result;
var view = new DataView(contents);
var int_array = [];
for (var i = 0; i < view.byteLength; i++) {
int_array.push(view.getUint8(i));
}
console.log('will send array now');
if (!is_chrome) {
var port = chrome.runtime.connect({
name: "filepicker-to-extension"
});
port.postMessage({
'destination': 'extension',
'message': 'import',
'args': {
'data': int_array
}
});
} else {
chrome.runtime.sendMessage({
'destination': 'extension',
'message': 'import',
'args': {
'data': int_array
}
});
}
//don't close the window, we reuse it to display html
//window.close();
}

View File

@@ -1,5 +0,0 @@
//globals from main.js cannot be overridden in nodejs unless we put them in a separate file
var chosen_notary;
var is_chrome = window.navigator.userAgent.match('Chrome') ? true : false;
//Future use: use TLS extension when user selects it in options
var use_max_fragment_length = false;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 501 B

View File

@@ -1,385 +0,0 @@
var db;
var db_blobs;
async function init_db() {
return new Promise(function(resolve, reject) {
var dbReq = indexedDB.open('PageSigner', 1);
dbReq.onupgradeneeded = function (event) {
// Set the db variable to our database so we can use it!
db = event.target.result;
if (!db.objectStoreNames.contains('sessions')) {
db.createObjectStore('sessions', { keyPath: 'creationTime', autoIncrement: true });
}
if (!db.objectStoreNames.contains('preferences')) {
let preferences = db.createObjectStore('preferences', { keyPath: 'name', autoIncrement: true });
preferences.add({name:'testing', value:false});
preferences.add({name:'verbose', value:true});
preferences.add({name:'verifiedOracles', value:[]});
}
};
dbReq.onsuccess = function (event) {
db = event.target.result;
resolve()
};
dbReq.onerror = function (event) {
alert('error opening database ' + event.target.errorCode);
};
}).
then(function(){
return new Promise(function(resolve, reject) {
//We must create a separate DB for blobs. Having a separate store is not a solution because
//i/o operations a very slow when there's blobs in a db
var dbReq2 = indexedDB.open('PageSigner_blobs', 1);
dbReq2.onupgradeneeded = function (event) {
// Set the db variable to our database so we can use it!
db_blobs = event.target.result;
if (!db_blobs.objectStoreNames.contains('sessions')) {
db_blobs.createObjectStore('sessions', { keyPath: 'creationTime', autoIncrement: true });
}
};
dbReq2.onsuccess = function (event) {
db_blobs = event.target.result;
resolve()
};
dbReq2.onerror = function (event) {
alert('error opening database ' + event.target.errorCode);
};
})
})
}
async function addNewPreference(key, value){
//check if the preference already exists
var p = new Promise(function(resolve, reject) {
let tx = db.transaction(['preferences'], 'readonly');
let store = tx.objectStore('preferences');
let req = store.getAll();
req.onsuccess = function(event) {
// The result of req.onsuccess is an array
resolve(event.target.result)
console.log('end db')
}
req.onerror = function(event) {
alert('error in cursor request ' + event.target.errorCode);
reject('error in cursor request ' + event.target.errorCode)
}
})
var allPreferences = await p;
for (let pref of allPreferences){
if (pref['name'] == key){
return;
}
}
//preference does not exist, add it
return new Promise(function(resolve, reject) {
let tx = db.transaction(['preferences'], 'readwrite');
let store = tx.objectStore('preferences');
store.add({name:key, value:value});
tx.oncomplete = function() {
resolve();
}
tx.onerror = function(event) {
alert('error storing ' + event.target.errorCode);
reject();
}
})
}
//converts all binary pgsgs into json format
async function convert_db(){
var all = new Promise(function(resolve, reject) {
console.log('begin db')
let tx = db_blobs.transaction(['sessions'], 'readwrite');
let store = tx.objectStore('sessions');
let req = store.getAll();
req.onsuccess = function(event) {
// The result of req.onsuccess is an array
resolve(event.target.result)
console.log('end db')
}
req.onerror = function(event) {
alert('error in cursor request ' + event.target.errorCode);
reject('error in cursor request ' + event.target.errorCode)
}
})
var allSessions = await all;
for (let session of allSessions){
var id = session['creationTime']
var p = new Promise(function(resolve, reject) {
// Start a database transaction and get the object store
let tx = db_blobs.transaction(['sessions'], 'readwrite');
let sessions = tx.objectStore('sessions')
var request = sessions.get(id)
request.onsuccess = function(event) {
// Get the old value that we want to update
var data = event.target.result;
// update the value(s) in the object that you want to change
var oldPgsg = data.pgsg
if (oldPgsg.slice == undefined){
//a json object which we don't need to touch
resolve();
return;
}
var newPgsg = convertPgsg(oldPgsg)
data.pgsg = JSON.parse(ba2str(newPgsg));
// Put this updated object back into the database.
var requestUpdate = sessions.put(data);
requestUpdate.onerror = function(event) {
// Do something with the error
reject()
};
requestUpdate.onsuccess = function(event) {
// Success - the data is updated!
resolve();
};
};
})
await p;
}
}
function deleteSession(session) {
return new Promise(function(resolve, reject) {
let tx = db.transaction(['sessions'], 'readwrite');
let sessions = tx.objectStore('sessions')
var req = sessions.delete(session);
req.onsuccess = function(event) {
resolve()
};
}).
then(function(){
return new Promise(function(resolve, reject) {
let tx = db_blobs.transaction(['sessions'], 'readwrite');
let sessions = tx.objectStore('sessions')
var req = sessions.delete(session);
req.onsuccess = function(event) {
resolve()
};
})
})
}
async function getAllSessions() {
return new Promise(function(resolve, reject) {
console.log('begin db')
let tx = db.transaction(['sessions'], 'readonly');
let store = tx.objectStore('sessions');
let req = store.getAll();
req.onsuccess = function(event) {
// The result of req.onsuccess is an array
resolve(event.target.result)
console.log('end db')
}
req.onerror = function(event) {
alert('error in cursor request ' + event.target.errorCode);
reject('error in cursor request ' + event.target.errorCode)
}
})
}
async function createNewSession (creationTime, commonName, notaryName, cleartext, pgsg, is_imported){
return new Promise(function(resolve, reject) {
let tx = db.transaction(['sessions'], 'readwrite');
let store = tx.objectStore('sessions');
let was_imported = false;
if (is_imported == true) was_imported = true;
let entry = {creationTime: creationTime, sessionName: commonName,
serverName:commonName, notaryName:notaryName, is_imported:was_imported};
store.add(entry);
tx.oncomplete = function() {
resolve();
}
tx.onerror = function(event) {
alert('error storing note ' + event.target.errorCode);
reject();
}
}).
then(function(){
return new Promise(function(resolve, reject) {
let tx2 = db_blobs.transaction(['sessions'], 'readwrite');
let store2 = tx2.objectStore('sessions');
//sessionName can be changed by the user in the manager window
let entry2 = {creationTime: creationTime, serverName:commonName, cleartext:cleartext, pgsg:pgsg};
store2.add(entry2);
tx2.oncomplete = function() {
resolve();
}
tx2.onerror = function(event) {
alert('error storing note ' + event.target.errorCode);
reject();
}
})
})
}
async function getSession(idx){
return new Promise(function(resolve, reject) {
let tx = db.transaction(['sessions'], 'readonly');
let store = tx.objectStore('sessions')
let req = store.get(idx);
req.onsuccess = function(event) {
let entry = event.target.result;
if (entry) {
console.log(entry);
resolve(entry)
} else {
console.log("entry 1 not found")
resolve(null)
}
}
req.onerror = function(event) {
console.log('error getting entry 1 ' + event.target.errorCode);
reject('error getting entry 1 ' + event.target.errorCode)
}
})
}
//get data from blob store
async function getSessionBlob(idx){
return new Promise(function(resolve, reject) {
let tx = db_blobs.transaction(['sessions'], 'readonly');
let store = tx.objectStore('sessions')
let req = store.get(idx);
req.onsuccess = function(event) {
let entry = event.target.result;
if (entry) {
console.log(entry);
resolve(entry)
} else {
console.log("note 1 not found")
resolve(null)
}
}
req.onerror = function(event) {
console.log('error getting entry 1 ' + event.target.errorCode);
reject('error getting entry 1 ' + event.target.errorCode)
}
})
}
async function getPref(pref){
return new Promise(function(resolve, reject) {
let tx = db.transaction(['preferences'], 'readonly');
let store = tx.objectStore('preferences')
let req = store.get(pref);
req.onsuccess = function(event) {
let entry = event.target.result;
if (entry) {
console.log(entry);
resolve(entry.value)
} else {
console.log("entry 1 not found")
resolve(null)
}
}
req.onerror = function(event) {
console.log('error getting entry 1 ' + event.target.errorCode);
reject('error getting entry 1 ' + event.target.errorCode)
}
})
}
function setPref(pref, newvalue) {
return new Promise(function(resolve, reject) {
let tx = db.transaction(['preferences'], 'readwrite');
let store = tx.objectStore('preferences')
var request = store.get(pref)
request.onsuccess = function(event) {
// Get the old value that we want to update
var data = event.target.result;
// update the value(s) in the object that you want to change
data.value = newvalue;
// Put this updated object back into the database.
var requestUpdate = store.put(data);
requestUpdate.onerror = function(event) {
// Do something with the error
reject()
};
requestUpdate.onsuccess = function(event) {
// Success - the data is updated!
resolve();
};
};
})
}
function renameSession(id, newname) {
return new Promise(function(resolve, reject) {
console.log('about to rename');
// Start a database transaction and get the notes object store
let tx = db.transaction(['sessions'], 'readwrite');
let sessions = tx.objectStore('sessions')
var request = sessions.get(id)
request.onsuccess = function(event) {
// Get the old value that we want to update
var data = event.target.result;
// update the value(s) in the object that you want to change
data.sessionName = newname;
// Put this updated object back into the database.
var requestUpdate = sessions.put(data);
requestUpdate.onerror = function(event) {
// Do something with the error
reject()
};
requestUpdate.onsuccess = function(event) {
// Success - the data is updated!
resolve();
};
};
})
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

View File

@@ -1,137 +0,0 @@
body {
background-image: linear-gradient(to right bottom, #d1d1d1, #d8d8d8, #dfdfdf, #e7e7e7, #eeeeee);
}
a:link {
text-decoration: none;
color: #0000ff
}
a:visited {
text-decoration: none;
color: #0000ff;
}
a:hover {
text-decoration: underline;
color: #aa00aa;
}
a:active {
text-decoration: underline;
}
h1 {
text-shadow: 4px 4px 4px #CCCCCC;
}
/* Table 1 Style */
table.table1 {
font-family: "Trebuchet MS", sans-serif;
font-size: 16px;
font-weight: bold;
line-height: 1.4em;
font-style: normal;
border-collapse: separate;
}
.table1 thead th {
padding: 15px;
color: #fff;
text-shadow: 1px 1px 1px #568F23;
border: 1px solid #93CE37;
border-bottom: 3px solid #9ED929;
background-color: #9DD929;
background: -webkit-gradient( linear, left bottom, left top, color-stop(0.02, rgb(123, 192, 67)), color-stop(0.51, rgb(139, 198, 66)), color-stop(0.87, rgb(158, 217, 41)));
background: -moz-linear-gradient( center bottom, rgb(123, 192, 67) 2%, rgb(139, 198, 66) 51%, rgb(158, 217, 41) 87%);
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius: 5px 5px 0px 0px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.table1 thead th:empty {
background: transparent;
border: none;
}
.table1 tbody th {
color: #fff;
text-shadow: 1px 1px 1px #568F23;
background-color: #9DD929;
border: 1px solid #93CE37;
border-right: 3px solid #9ED929;
padding: 0px 10px;
background: -webkit-gradient( linear, left bottom, right top, color-stop(0.02, rgb(158, 217, 41)), color-stop(0.51, rgb(139, 198, 66)), color-stop(0.87, rgb(123, 192, 67)));
background: -moz-linear-gradient( left bottom, rgb(158, 217, 41) 2%, rgb(139, 198, 66) 51%, rgb(123, 192, 67) 87%);
-moz-border-radius: 5px 0px 0px 5px;
-webkit-border-top-left-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.table1 tfoot td {
color: #9CD009;
font-size: 32px;
text-align: center;
padding: 10px 0px;
text-shadow: 1px 1px 1px #444;
}
.table1 tfoot th {
color: #666;
}
.table1 tbody td {
padding: 0px;
text-align: center;
background-color: #DEF3CA;
border: 2px solid #E7EFE0;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
color: #666;
text-shadow: 1px 1px 1px #fff;
height: 10px !important;
}
.table1 tbody tr {
height: 10px;
}
.table1 tbody span.check::before {
content: url(chrome://pagesigner/content/check.png)
}
button {
margin: 0px;
padding: 0px;
font-family: Lucida Sans MS, Tahoma;
font-size: 12px;
color: #000;
white-space: nowrap;
width: 95%;
overflow: visible;
height: auto;
}
button em {
/*vertical-align:middle;
margin:0 2px;
display:inline-block;
width:24px;
height:auto;*/
background-image: url(chrome://pagesigner/content/refresh.png);
}
button em.leftImage {
background-position: left center;
}
button em.rightImage {
background-position: -64px -16px;
}

View File

@@ -1,96 +0,0 @@
<head>
<title>Manage your PageSigner notarization sessions.</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="PageSigner" />
<link rel="stylesheet" href="manager.css" type="text/css" media="screen" />
<link rel="stylesheet" type="text/css" href="sweetalert.css">
<style>
body{
margin-top: 20px;
margin-bottom: 20px;
margin-left: 60px;
margin-right: 60px;
/*width: 16em;*/
/* Fonts Chrome specifies for each OS: */
/* Linux: 'DejaVu Sans', Arial, sans-serif */
/* Mac: 'Lucida Grande', sans-serif */
/* Windows: 'Segoe UI', Tahoma, sans-serif */
font-family: 'Lucida Grande', 'Segoe UI', Tahoma, 'DejaVu Sans', Arial, sans-serif;
font-size: 75%;
}
a {
cursor: pointer;
cursor: hand;
text-decoration: underline;
color: blue;
}
#toprightimg {
position: relative;
}
#toprightimg img {
position: absolute;
top: 0px;
right: 0px;
}
.myButton {
box-shadow: 0px 10px 14px -7px #3e7327;
background:linear-gradient(to bottom, #77b55a 5%, #72b352 100%);
background-color:#77b55a;
border-radius:4px;
border:1px solid #4b8f29;
display:inline-block;
cursor:pointer;
color:#ffffff;
font-family:Arial;
font-size:13px;
font-weight:bold;
padding:6px 12px;
text-decoration:none;
text-shadow:0px 1px 0px #5b8a3c;
}
.myButton:hover {
background:linear-gradient(to bottom, #72b352 5%, #77b55a 100%);
background-color:#72b352;
}
.myButton:active {
position:relative;
top:1px;
}
</style>
</head>
<body>
<textarea hidden id="extension2manager"></textarea>
<textarea hidden id="manager2extension"></textarea>
<div id="mydata">
<table class="table1" id="myTableData" width="100%">
<thead>
<tr>
<th scope='col' colspan='4' >Notarization session</th>
<th scope='col' >Time</th>
<th scope='col' hidden>Verified</th>
<th scope='col' >Verifier</th>
<th scope='col' >View Data</th>
</tr>
</thead>
<tbody id="myTableBody">
</tbody>
</table>
</div>
<script src="manager.js"></script>
<script src="sweetalert.min.js"></script>
</body>
</html>

View File

@@ -1,304 +0,0 @@
var is_chrome = window.navigator.userAgent.match('Chrome') ? true : false;
var port;
var tabid = null;
var is_manager = true;
var table_populated = false; //used in testing only
function prepare_testing(){
var script = document.createElement('script');
script.src = 'testing/manager_test.js';
document.body.appendChild(script);
}
function onload() {
if (is_chrome) {
chrome.runtime.onMessage.addListener(function(data) {
if (data.destination != 'manager') return;
if (data.command == 'payload'){
console.log('hooray', data.payload);
process_data(data.payload);
}
else if (data.command == 'export'){
function ba2ab(ba) {
var ab = new ArrayBuffer(ba.length);
var dv = new DataView(ab);
for (var i = 0; i < ba.length; i++) {
dv.setUint8(i, ba[i]);
}
return ab;
};
//converts string to bytearray
function str2ba(str) {
if (typeof(str) !== "string") {
throw ("Only type string is allowed in str2ba");
}
ba = [];
for (var i = 0; i < str.length; i++) {
ba.push(str.charCodeAt(i));
}
return ba;
}
//.payload contains {pgsg: pgsg_blob, name: session_name}
var str = data.payload.pgsg
var ab = ba2ab(str2ba(str));
var exportedBlob = new Blob([ab]);
var exportedBlobUrl = URL.createObjectURL(exportedBlob, {
type: 'application/octet-stream'
});
var fauxLink = document.createElement('a');
fauxLink.href = exportedBlobUrl;
fauxLink.setAttribute('download', data.payload.name+'.pgsg');
document.body.appendChild(fauxLink);
fauxLink.click();
}
});
} else {
port = chrome.runtime.connect({
name: "manager-to-extension"
});
port.onMessage.addListener(function(data) {
//console.log("Message from legacy add-on: ", data);
process_data(data.payload);
});
}
sendMessage({
'destination': 'extension',
'message': 'refresh'
});
}
document.addEventListener('load', onload);
window.addEventListener('load', onload);
function process_data(rows) {
tb = document.getElementsByTagName('tbody')[0];
var initial_row_length = tb.rows.length;
for (var j = 0; j < initial_row_length; j++) {
tb.deleteRow(0);
}
//create descending sort order based on creation time
rows.sort(function(a, b) {
var as = a.creationTime,
bs = b.creationTime;
return as == bs ? 0 : (as < bs ? 1 : -1);
});
for (var i = 0; i < rows.length; i++) {
var r = rows[i];
addRow({
'sessionName': r.sessionName,
'serverName': r.serverName,
'is_imported': r.is_imported,
'verifier': r.verifier,
'creationTime': r.creationTime,
});
}
table_populated = true;
}
function addRow(args) {
var session = args.creationTime;
var tb, row, td, a, img, text;
tb = document.getElementById('myTableBody');
row = tb.insertRow(tb.rows.length);
td = document.createElement("td");
td.id = 'toprightimg';
td.appendChild(document.createTextNode(args.sessionName));
var importimg = document.createElement("img");
importimg.src = 'import.png';
importimg.width = 12;
importimg.height = 12;
importimg.id = 'topright';
importimg.title = 'This notarization file was imported';
if (!args.is_imported) {
importimg.hidden = true;
}
td.appendChild(importimg);
row.appendChild(td);
td = document.createElement("td");
div = document.createElement("input");
div.type = 'button'
div.title = 'Give the file a more memorable name';
div.style = 'float: right';
div.onclick = function(event) {
doRename(event.target, session);
};
div.value = 'Rename';
div.className = 'myButton'
td.appendChild(div);
row.appendChild(td);
td = document.createElement("td");
a = document.createElement("input");
a.type = 'button'
a.className = 'myButton'
a.title = 'Save the file so you can transfer it to others';
a.style = 'float: right';
a.onclick = function(event) {
console.log('export clicked');
swal({
title: 'You MUST LOG OUT before exporting',
text: 'Before exporting you MUST LOG OUT of any sessions associated with the data you are about to export. Please LOG OUT NOW if you have any active sessions running and press OK to proceed',
type: "warning"
},
function() {
sendMessage({
'destination': 'extension',
'message': 'export',
'args': {
'dir': session
}
});
})
};
a.value = 'Export';
td.appendChild(a);
row.appendChild(td);
td = document.createElement("td");
a = document.createElement("input");
a.type = 'button'
a.className = 'myButton'
a.title = 'permanently remove this set of files from disk';
a.style = 'float: right';
a.onclick = function(event) {
swal({
title: 'Removing notarization data',
text: "This will remove all notarized data of " + args.sessionName + ". Are you sure?",
type: "warning"
},
function() {
sendMessage({
'destination': 'extension',
'message': 'delete',
'args': {
'dir': session
}
});
});
};
a.value = 'Delete';
td.appendChild(a);
row.appendChild(td);
td = document.createElement("td");
td.textContent = args.creationTime;
row.appendChild(td);
// td = document.createElement("td");
// img = document.createElement("img");
// img.height = 30;
// img.width = 30;
// var label;
// if (args.valid) {
// img.src = 'check.png';
// label = 'valid';
// } else {
// img.src = 'cross.png';
// label = 'invalid';
// }
// text = document.createElement("text");
// text.textContent = label;
// td.appendChild(img);
// td.appendChild(text);
// row.appendChild(td);
td = document.createElement("td");
td.textContent = args.verifier;
row.appendChild(td);
td = document.createElement("td");
a = document.createElement("input");
a.type = 'button'
a.className = 'myButton'
a.onclick = function(event) {
sendMessage({
'destination': 'extension',
'message': 'viewdata',
'args': {
'dir': session
}
});
};
a.value = "view";
a.style = "margin-right: 20px;"
td.appendChild(a);
a = document.createElement("input");
a.type = 'button'
a.className = 'myButton'
a.onclick = function(event) {
sendMessage({
'destination': 'extension',
'message': 'viewraw',
'args': {
'dir': session
}
});
};
a.value = "raw";
td.appendChild(a);
row.appendChild(td);
}
function doRename(t, dir) {
var isValid = (function() {
var rg1 = /^[^\\/:\*\?"<>\|]+$/; // forbidden characters \ / : * ? " < > |
var rg2 = /^\./; // cannot start with dot (.)
var rg3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; // forbidden file names
return function isValid(fname) {
if (typeof(fname) !== "string") return false;
return rg1.test(fname) && !rg2.test(fname) && !rg3.test(fname);
};
})();
swal({
title: "Enter a new name for the notarization file",
type: "input",
inputPlaceholder: "Write something"
},
function(new_name) {
if (!(isValid(new_name))) {
console.log('detected invalid name', new_name);
//swal glitch - need a timeout
setTimeout(function() {
swal({
title: "Invalid filename",
text: 'Please only use alphanumerical characters',
type: 'warning'
});
}, 200);
} else if (new_name === null) return; //escape pressed
else {
sendMessage({
'destination': 'extension',
'message': 'rename',
'args': {
'dir': dir,
'newname': new_name
}
});
}
});
}
function sendMessage(msg) {
if (is_chrome) {
chrome.runtime.sendMessage(msg);
} else {
port.postMessage(msg);
}
}

View File

@@ -1,100 +0,0 @@
var is_chrome = window.navigator.userAgent.match('Chrome') ? true : false;
function install_bar(sessionId, serverName, hideButton) {
if (hideButton === undefined) {
hideButton = false;
}
var table = document.createElement("table");
table.style.position = "fixed";
table.style.top = "0px";
table.style.left = "100px";
table.style.background = "rgba(242, 241, 240, 0.9)";
table.style.width = "80%";
table.style.height = "32px";
table.style.visibility = 'hidden';
table.style.opacity = '0';
table.style.webkitTransition = 'visibility 0s 2s, opacity 2s linear';
table.style.transition = 'visibility 0s 2s, opacity 2s linear';
var row = document.createElement("tr");
var cell1 = document.createElement("td");
var cell2 = document.createElement("td");
var cell3 = document.createElement("td");
var cell4 = document.createElement("td");
cell3.style.align = "right";
cell4.style.align = "right";
var img = document.createElement("img");
//icon.png base64-encoded
img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAS2QAAEtkBYE3f7AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAlySURBVHic5Zt7cFT1Fcc/597NJimgqICvGR8dO07V8YG0HaRDdolkg9rio6SPcaoZaSlko0DVCj6Y+Gi14AOyCzLVYp36IuMDK7orj71RxKJorUOtOlbrozOUoBUiJCTZ3+kfuwubzSbZezfQzfT7V36Pc37nfnN+597f75yVwJWJivKvMVOFXwCnM3zQichq0eTSWGTKm16VWOmHb2Z4PTxABao/Vay1E2a9UeZViZX+zw9nHHOUr326V2GL4fef7wuLM7yL/p/D109/J/DeoTSkQBwOnDSUCvsj4L14JHD2UC40FAg1OhejPD2UOvsjYFhBVN/J/F3b4Jyiwp0gx6K6F9HXxdJnYsumvJZP9pDEgOAsZ0xTU9PBWuvVWCS4GmDCrDfKVHgOuAz0PITzQRaosbaEws6mUNi5KFf4oHhAbTgxXZFpwBnA6f4yRm9uq+oINTrvoGxT2NQ9locSiwI9RS6llso1mcaRZbsbQU7tZ+4k4E814cQqqexujC+u2QND7AHT5mw4sybsJBR5BpiVXnR0ergS5VzgCoHf+dt4e2pjIlTMegJ/eCFa9TrABVe/PFaQWwaXkXrtKH/t/LkbjoYhJKC2MXGrsew3BQIFinzTUomFwk5LsMnx4onttrIg00gaczupt8SgEPQ0u8eOTb/qlVFDsgVCYecKkJvzDG1H2YalHylynCin0/c19gN/G58B89ysKXDH2mhgO0BNg3O2iMx0afbZ+yq75hVNQGhO4lwsuT+n+0tRbj6srW3F6tUzktkDtY2Jy1RlCb2JmBtqcLbGo4FHClz2H5bVcV+mISJLQV17syI/L34L2BIBKg50yF7LJKti0UAk9+EBYs3BJ5MkJyh83GtAWFHoVhD0l88vm7YPoKaxdQboZE+2Kx8WRcB581/NBLYs68y8F5ZXvz2Q3PpI9eeWZepyukeV7WTwjy9lfSwSXAMQrHcqUF3s0uz9MLCwKAJGdnZ+G8g+impSzZOFyKY+TOSTnO5JAwopPZgDscI/gmsFTizU3hw8vi4a2FQUASLW+Jyuf66PVH9euAZ9o5c+JFdfL9hWx7r4isA2gOrZG48Hbih8rV7oQK3roejXoJbndHS5E8+Zb/ro64XMvgfw2dZdwAhX6x1Y9654dPKnMEzPAtPCrROBn3iTlk/ay/2/zbSG3X2ACJJElwLiTYFev/meiR2ZpicPqA0n6hSZieRGbTk5FHbeLdwYjstpXxAKO5tBH49HgsvyiUyd41wh8C33VgPKy/FI4InsLtcEXBjeeKJiPZJfVv1Af4eRQjAKmAgysbbBeT8WDcSyB4MNzki/xa9RL6rFGPvAwSkD11ugB2sihyB2GOl7pvBb3IhyrBd9gv5+3bLJf8ntHzYxYOqcDV9H3Z0XsrBLk1035hsoWQIENdltS+y7gQFfk/3qUm6Lr6jZkW+sVAlQsdgfrGrCiWqEi70oEuT9nT2j8gZUKFkC5LHYsuBfAerqWmwRuW8wiX5hzPytK8/t7m+4FAnoNqZn/93CrrFjZqGeEx+x2PLg2oEmlBwBKqxct7z6Q4CL5mw6ApFbParqRgYPmqVGwFfS03VbptFtdTcBR3nSJBqJNwcG/SgrKQIUuScTrS+4esNpILM9qmrr8hXmOSVEgOyo7PAtybSS6rsXrx9cojcl7g18WcjUkiFAxMxb8+CkdoBQQ+v3UK3xqOqt88a89EChk90TINYWoNiERi6eizUHHwWoa2rxI3qPV0VqdO6iRYvM4DNTcO1i8ebJH4UancuB2SgnAEaQpKJGESOiBiUpilELg0oSUYOKEdSokEQxAkbBgL5rW53XZfTvaht3Degpbu0CEGiJLw+2upHxtMfizYEngCcGnegS58/dcLSN7yaP4p025rrBp/VGycQAALvbvgP0MC+yIrp4bWTKx4PP7I2SIaA2vHE8IvUexT/zd+2504tgyRCgWHd6ye4AiOivnl150V4vsqV0Kfpdb2KyOdYceNTroiXhAek6v0oPoqqifa653KAkCBhXvjdTQ4BAtE/esB8o+tCLzYGtxaw9pAR4zPNjksn9ef3yjrIF66KBk9VoAOWZAcTajc8sGGC8IAwJAbXhjeNDYecxfxv/qWlo/bFbeWPtryJJrnlwUrsq+uLyYGs8GrgEZCH0vQdW0dvX31f972JtL5qA2ganVrE2AT8CRlrCBNdKVNMeIHuC9U5F9lA8UvUbQS+h9+f3B6PH7Nx/S1QzJ1HlwXSgSAJC4dapKrKGrACmou2ujZCMB+hh/hF8FGp0rs0UQE+du/6E9LE4vb3kE8H8cPWiGV0A0xoSl4otQa/P4JmA1HldW9LJkDTE+NSscqtLtVdtzzEoi8f42reEGpwbrB7fNoUQoKrcX9HhOyNTHl87P36kEVmSX2th8BS0QrNfHIftX0uqKGkPB7K0O03Scp2zUxidK6TCOcA5qZZ8KMrMeLQqkRmfftUro0xleUzgZC/PkIFrDwjWOxXY/mdJ1fi0AduzzB5nbNlSG3ZW1TW1+PNryGtGP9VdYkCWUbnvzFjWw9c1tfj3VXY/7TlHmAVXHiCChBp4WOE7QAfwFKl6wCzoOIUrd7eN+2Jqw0sP2JK0kmKniLa7dvV0+75IRANf9dJ7oJYwq0/eT6petS4a2JTd39TUZO1uq/qjQrUb2/uDKwJqGhJ3KDIDxFhqLjfI+HSS+kngUlIp6yRgKzrfEp2vCFYmydPjwy8QCrd2ofqx2ObyVKmM2ZeV7U6i3Lu73H9Ldho7g81tkyPADK8PnIuCCahtbK0HWQAgqte/EA0+VVfXsmbX2KNXJsu6u+we30TQ9xD9AJWfpaTkC+DPqAoWR6ByAuixoH6Eb5C0zwJe60nqUp8tQZDdYBbGo8EteW24OnFWEReleVEQAaHwxslgrUy1dEUsGrwbIF0G92l62vGQihH+EWwUS/8ebw68rdr7IyZY71T4R3KSwsh4pGorwIYVU/5FAftZDRWDzXGLgghQsWaIUgby/OE72hoHmptYFegEHgcgT0YuPV54EUUWjEqZ+3fMwCjoLVC5t2yhKNMO37Hj+/mKHw8VbMTzr8P6Q0EekL6ujg068SAjaRm/pUPrAiVxHC4Ulh46Dzg1FHbeGurFhgCeLkwHQn8EVABnDfVipYhhtQUOBizgb/9rI4qGYZtXUUuU3B87DDds/7xn1Bqvwta+vTwgSiPDzxM6EXlYMBcOVAM0GP4LS9tKkcQmJqcAAAAASUVORK5CYII=";
img.height = 16;
img.width = 16;
var text = document.createElement("text");
text.textContent = "PageSigner verified that this page was received from ";
var domain = document.createElement("text");
domain.id = "domainName";
domain.textContent = serverName;
var button = document.createElement("button");
button.id = "viewRaw";
button.textContent = "View raw data";
button.style.MozBorderRadius = "4px";
button.style.WebkitBorderRadius = "4px";
button.style.borderRadius = "4px";
button.onclick = function() {
if (is_chrome) {
chrome.runtime.sendMessage({
destination: 'extension',
message: 'viewraw',
args: {
dir: sessionId
}
});
} else {
var port = chrome.runtime.connect({
name: "notification-to-extension"
});
port.postMessage({
'destination': 'extension',
'message': 'viewraw',
args: {
dir: sessionId
}
});
}
};
if (hideButton) {
button.hidden = true;
}
var close = document.createElement("a");
close.text = "x";
close.style = 'cursor: pointer;';
close.onclick = function(event) {
document.getElementById('tablediv').hidden = true;
}
cell4.appendChild(close);
cell3.appendChild(button)
cell2.appendChild(text);
cell2.appendChild(domain);
cell1.appendChild(img);
row.appendChild(cell1);
row.appendChild(cell2);
row.appendChild(cell3);
row.appendChild(cell4);
table.appendChild(row);
var tablediv = document.createElement('div');
tablediv.appendChild(table);
tablediv.id = 'tablediv';
document.body.appendChild(tablediv);
setTimeout(function() {
//make a transition to visible
table.style.visibility = 'visible';
table.style.opacity = '1';
table.style.webkitTransition = 'opacity 2s linear';
table.style.transition = 'opacity 2s linear';
}, 0);
}

View File

@@ -1,6 +0,0 @@
This folder contains notarization files of previous oracles done by the succeeding oracle, e.g.
suppose that we switched from tlsnotarygroup8 to tlsnotarygroup9. We notarize tlsnotarygroup8's AWS URLs using the newly-launched tlsnotarygroup9 oracle and placed the notarization files into the tlsnotarygroup8 folder.
Whenever a user imports an old pgsg notarized by tlsnotarygroup8, we verify each file in the tlsnotarygroup8 folder to ascertain that tlsnotarygroup8 was indeed a properly set up oracle.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,332 +0,0 @@
var oracles_intact = false; //will be set to true after the oracle check completes
var old_oracle = {
'snapshotId': 'snap-0bf942f29a64f0f50',
'imageId': 'ami-016509fc994427733',
'name': 'tlsnotarygroup9',
'IP': '35.174.184.105',
'instanceId': 'i-04f8cbc53fcc36f1d',
'pubkeyPEM': '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaXM2Lxec8G3XJ6P86J3Qng+DKNzP\n0zGPlI7AqNLr+kCZ0obomrcvGS8QO0xyAVUaqK+oNIWFVKQf6LZPwP9m4w==\n-----END PUBLIC KEY-----'
}
var oracle = {
'snapshotId': 'snap-0ca15091021ef43fc',
'imageId': 'ami-08514e4e0cd45a2f4',
'name': 'tlsnotarygroup10',
'IP': '54.174.129.130',
'port': '10011',
'DI':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeInstances&Expires=2030-01-01&InstanceId=i-0b39e16ddbb48f05e&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=DSk%2B%2BwQqVGPv%2FC5vyq8zvfFHxSFvLkmXsGipeNUYBQQ%3D',
'DV':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeVolumes&Expires=2030-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&VolumeId=vol-0d245f72f3413ae86&Signature=EDM414fdY2jHT0mhGofbuJU73vqwLWlKnJgOsw8U4dc%3D',
'GCO':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=GetConsoleOutput&Expires=2030-01-01&InstanceId=i-0b39e16ddbb48f05e&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=ekQyfK7f%2FSj9i%2B5fiLc4B3Wui2fz9JmW2%2BGtSNgtr0o%3D',
'GU':'https://iam.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=GetUser&Expires=2030-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-05-08&Signature=jgeLNTQY1yVtUs2JCChV1AlzaQLkyn6%2BKx%2BQIxmlLew%3D',
'DIAud':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeInstanceAttribute&Attribute=userData&Expires=2030-01-01&InstanceId=i-0b39e16ddbb48f05e&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=LSb9dFBO0faQvY9EjjF6axvQoal%2FqmMcAiruMJchBxg%3D',
'DIAk':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeInstanceAttribute&Attribute=kernel&Expires=2030-01-01&InstanceId=i-0b39e16ddbb48f05e&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=XWMW8%2FaGlZn2%2BgJGCmj%2FXHQ5%2FELC%2Bs0pWgpSzv2dcfw%3D',
'DIAr':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeInstanceAttribute&Attribute=ramdisk&Expires=2030-01-01&InstanceId=i-0b39e16ddbb48f05e&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=%2BhpRfE08kuIuNC9irB0YkoHxLzEvcjomGcgbdfE31MA%3D',
'DImg':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAI2NJVYXCCAQDCC5Q&Action=DescribeImages&Expires=2030-01-01&ImageId.1=ami-08514e4e0cd45a2f4&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=CHGkCkAEshf366SEVqz091IHM0ifQmmvIpXtrTeKNyA%3D',
'instanceId': 'i-0b39e16ddbb48f05e',
'pubkeyPEM': '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7kyCJQVb6z2qqZmwxE3Uhqtpg0b6\nTn4YzrusUrajjARpy11GvrCpJaa+6LjUwZVNAS6fQ1s7LthGa2AHRJeWpQ==\n-----END PUBLIC KEY-----'
}
//there can be potentially multiple oracles to choose from
var oracles = [];
oracles.push(oracle);
//assuming both events happened on the same day, get the time
//difference between them in seconds
//the time string looks like "2015-04-15T19:00:59.000Z"
function getSecondsDelta(later, sooner) {
assert(later.length == 24);
if (later.slice(0, 11) !== sooner.slice(0, 11)) {
return 999999; //not on the same day
}
var laterTime = later.slice(11, 19).split(':');
var soonerTime = sooner.slice(11, 19).split(':');
var laterSecs = parseInt(laterTime[0]) * 3600 + parseInt(laterTime[1]) * 60 + parseInt(laterTime[2]);
var soonerSecs = parseInt(soonerTime[0]) * 3600 + parseInt(soonerTime[1]) * 60 + parseInt(soonerTime[2]);
return laterSecs - soonerSecs;
}
function checkDescribeInstances(xmlDoc, instanceId, IP, imageId) {
try {
assert(xmlDoc.getElementsByTagName('DescribeInstancesResponse').length == 1)
var rs = xmlDoc.getElementsByTagName('reservationSet');
assert(rs.length === 1);
var rs_items = rs[0].children;
assert(rs_items.length === 1);
var ownerId = rs_items[0].getElementsByTagName('ownerId')[0].textContent;
var isets = rs_items[0].getElementsByTagName('instancesSet');
assert(isets.length === 1);
var instances = isets[0].children;
assert(instances.length === 1);
var parent = instances[0];
assert(parent.getElementsByTagName('instanceId')[0].textContent === instanceId);
assert(parent.getElementsByTagName('imageId')[0].textContent === imageId);
assert(parent.getElementsByTagName('instanceState')[0].getElementsByTagName('name')[0].textContent === 'running');
var launchTime = parent.getElementsByTagName('launchTime')[0].textContent;
assert(parent.getElementsByTagName('ipAddress')[0].textContent === IP);
assert(parent.getElementsByTagName('rootDeviceType')[0].textContent === 'ebs');
assert(parent.getElementsByTagName('rootDeviceName')[0].textContent === '/dev/xvda');
var devices = parent.getElementsByTagName('blockDeviceMapping')[0].getElementsByTagName('item');
assert(devices.length === 1);
assert(devices[0].getElementsByTagName('deviceName')[0].textContent === '/dev/xvda');
assert(devices[0].getElementsByTagName('ebs')[0].getElementsByTagName('status')[0].textContent === 'attached');
var volAttachTime = devices[0].getElementsByTagName('ebs')[0].getElementsByTagName('attachTime')[0].textContent;
var volumeId = devices[0].getElementsByTagName('ebs')[0].getElementsByTagName('volumeId')[0].textContent;
//get seconds from "2015-04-15T19:00:59.000Z"
assert(getSecondsDelta(volAttachTime, launchTime) <= 2);
assert(parent.getElementsByTagName('virtualizationType')[0].textContent === 'hvm');
} catch (e) {
throw('checkDescribeInstances exception')
}
return {
'ownerId': ownerId,
'volumeId': volumeId,
'volAttachTime': volAttachTime,
'launchTime': launchTime
};
}
function checkDescribeVolumes(xmlDoc, instanceId, volumeId, volAttachTime, snapshotId) {
try {
assert(xmlDoc.getElementsByTagName('DescribeVolumesResponse').length == 1)
var volumes = xmlDoc.getElementsByTagName('volumeSet')[0].children;
assert(volumes.length === 1);
var volume = volumes[0];
assert(volume.getElementsByTagName('volumeId')[0].textContent === volumeId);
assert(volume.getElementsByTagName('snapshotId')[0].textContent === snapshotId);
assert(volume.getElementsByTagName('status')[0].textContent === 'in-use');
var volCreateTime = volume.getElementsByTagName('createTime')[0].textContent;
var attVolumes = volume.getElementsByTagName('attachmentSet')[0].getElementsByTagName('item');
assert(attVolumes.length === 1);
var attVolume = attVolumes[0];
assert(attVolume.getElementsByTagName('volumeId')[0].textContent === volumeId);
assert(attVolume.getElementsByTagName('instanceId')[0].textContent === instanceId);
assert(attVolume.getElementsByTagName('device')[0].textContent === '/dev/xvda');
assert(attVolume.getElementsByTagName('status')[0].textContent === 'attached');
var attTime = attVolume.getElementsByTagName('attachTime')[0].textContent;
assert(volAttachTime === attTime);
//Crucial: volume was created from snapshot and attached at the same instant
//this guarantees that there was no time window to modify it
assert(getSecondsDelta(attTime, volCreateTime) === 0);
} catch (e) {
throw('checkDescribeVolumes exception')
}
return true;
}
function checkGetConsoleOutput(xmlDoc, instanceId, launchTime, pubkeyPEM) {
try {
assert(xmlDoc.getElementsByTagName('GetConsoleOutputResponse').length == 1)
assert(xmlDoc.getElementsByTagName('instanceId')[0].textContent === instanceId);
var timestamp = xmlDoc.getElementsByTagName('timestamp')[0].textContent;
//prevent funny business: last consoleLog entry no later than 5 minutes after instance starts
//However, it was once observed that timestamp was switched on 2018-01-01. Maybe AWS resets it
//every first day of the year?
//Update Oct 2018.
//AWS spuriously changed the timestamp of an instance launched in Jan 2018 to Sep 2018.
//Commenting out the assert because otherwise we'd have to relaunch the oracle server after each
//such spurious glitch
//assert(getSecondsDelta(timestamp, launchTime) <= 300);
var b64data = xmlDoc.getElementsByTagName('output')[0].textContent;
var logstr = ba2str(b64decode(b64data));
var sigmark = 'PageSigner public key for verification';
var pkstartmark = '-----BEGIN PUBLIC KEY-----';
var pkendmark = '-----END PUBLIC KEY-----';
var mark_start = logstr.search(sigmark);
assert(mark_start !== -1);
var pubkey_start = mark_start + logstr.slice(mark_start).search(pkstartmark);
var pubkey_end = pubkey_start + logstr.slice(pubkey_start).search(pkendmark) + pkendmark.length;
var chunk = logstr.slice(pubkey_start, pubkey_end);
var lines = chunk.split('\n');
var pk = pkstartmark + '\n';
for (var i = 1; i < lines.length-1; i++) {
var words = lines[i].split(' ');
pk = pk + words[words.length-1] + '\n';
}
pk = pk + pkendmark;
assert(pk.length > 0);
assert(pk.split('\r\n').join('\n') == pubkeyPEM)
return true;
} catch (e) {
throw('checkGetConsoleOutput exception')
}
}
// "userData" allows to pass an arbitrary script to the instance at launch. It MUST be empty.
// This is a sanity check because the instance is stripped of the code which parses userData.
function checkDescribeInstanceAttributeUserdata(xmlDoc, instanceId) {
try {
assert(xmlDoc.getElementsByTagName('DescribeInstanceAttributeResponse').length == 1)
assert(xmlDoc.getElementsByTagName('instanceId')[0].textContent === instanceId);
assert(xmlDoc.getElementsByTagName('userData')[0].textContent === "");
} catch (e) {
throw('checkDescribeInstanceAttributeUserdata exception')
}
return true;
}
function checkDescribeInstanceAttributeKernel(xmlDoc, instanceId) {
try {
assert(xmlDoc.getElementsByTagName('DescribeInstanceAttributeResponse').length == 1)
assert(xmlDoc.getElementsByTagName('instanceId')[0].textContent === instanceId);
assert(xmlDoc.getElementsByTagName('kernel')[0].textContent === "");
} catch (e) {
throw('checkDescribeInstanceAttributeKernel exception')
}
return true;
}
function checkDescribeInstanceAttributeRamdisk(xmlDoc, instanceId) {
try {
assert(xmlDoc.getElementsByTagName('DescribeInstanceAttributeResponse').length == 1)
assert(xmlDoc.getElementsByTagName('instanceId')[0].textContent === instanceId);
assert(xmlDoc.getElementsByTagName('ramdisk')[0].textContent === "");
} catch (e) {
throw('checkDescribeInstanceAttributeRamdisk exception')
}
return true;
}
function checkGetUser(xmlDoc, ownerId) {
try {
assert(xmlDoc.getElementsByTagName('GetUserResponse').length == 1)
assert(xmlDoc.getElementsByTagName('UserId')[0].textContent === ownerId);
assert(xmlDoc.getElementsByTagName('Arn')[0].textContent.slice(-(ownerId.length + ':root'.length)) === ownerId + ':root');
} catch (e) {
throw('checkGetUser exception')
}
return true;
}
function checkDescribeImages(xmlDoc, imageId, snapshotId){
try {
assert(xmlDoc.getElementsByTagName('DescribeImagesResponse').length == 1)
var images = xmlDoc.getElementsByTagName('imagesSet')[0].children;
assert(images.length == 1);
var image = images[0];
assert(image.getElementsByTagName('imageId')[0].textContent == imageId);
assert(image.getElementsByTagName('rootDeviceName')[0].textContent == '/dev/xvda');
var devices = image.getElementsByTagName('blockDeviceMapping')[0].children;
assert(devices.length == 1);
var device = devices[0];
var ebs = device.getElementsByTagName('ebs')[0];
assert(ebs.getElementsByTagName('snapshotId')[0].textContent == snapshotId);
} catch (e) {
throw('checkDescribeImages exception')
}
return true;
}
async function fetch_and_parse(resource){
var text;
if (typeof(resource) == 'string'){
var req = await fetch(resource)
text = await req.text()
}
else if (typeof(resource) == 'object'){
text = resource.text
}
else {
throw('unknown resource type in fetch_and_parse')
}
var xmlDoc = new DOMParser().parseFromString(text, "text/xml")
return xmlDoc
}
async function check_oracle(o, isOld) {
var xmlDocDI = await fetch_and_parse(o.DI)
var rv = checkDescribeInstances(xmlDocDI, o.instanceId, o.IP, o.imageId);
var volumeId = rv.volumeId
var volAttachTime = rv.volAttachTime
var ownerId = rv.ownerId
var launchTime = rv.launchTime
var xmlDocDV = await fetch_and_parse(o.DV)
checkDescribeVolumes(xmlDocDV, o.instanceId, volumeId, volAttachTime, o.snapshotId);
var xmlDocGU = await fetch_and_parse(o.GU)
checkGetUser(xmlDocGU, ownerId);
var xmlDocGCO = await fetch_and_parse(o.GCO)
var result = checkGetConsoleOutput(xmlDocGCO, o.instanceId, launchTime, o.pubkeyPEM);
var xmlDocDIAud = await fetch_and_parse(o.DIAud)
checkDescribeInstanceAttributeUserdata(xmlDocDIAud, o.instanceId);
var xmlDocDIAk = await fetch_and_parse(o.DIAk)
checkDescribeInstanceAttributeKernel(xmlDocDIAk, o.instanceId);
var xmlDocDIAr = await fetch_and_parse(o.DIAr)
checkDescribeInstanceAttributeRamdisk(xmlDocDIAr, o.instanceId);
var xmlDocDImg = await fetch_and_parse(o.DImg)
checkDescribeImages(xmlDocDImg, o.imageId, o.snapshotId);
if (isOld == true){
//unfortunately there is no way to perform the 'AWSAccessKeyId=' check (see below)
//for an old oracle server
console.log('oracle verification successfully finished');
return true;
}
var mark = 'AWSAccessKeyId=';
var start;
var id;
var ids = [];
//"AWSAccessKeyId" should be the same to prove that the queries are made on behalf of AWS user "root".
//The attacker can be a user with limited privileges for whom the API would report only partial information.
for (var url in [o.DI, o.DV, o.GU, o.GCO, o.DIAud, o.DIAk, o.DIAr, o.DImg]) {
start = url.search(mark) + mark.length;
id = url.slice(start, start + url.slice(start).search('&'));
ids.push(id);
}
assert(new Set(ids).size === 1);
console.log('oracle verification successfully finished');
return true;
}
async function verifyOldOracle(name){
if (old_oracle.name != name){
return {result:false}
}
var o = old_oracle;
for (let key of ['DI', 'DV', 'GU', 'GCO', 'DIAud', 'DIAk', 'DIAr', 'DImg']){
var pgsg = await import_resource('old oracles/'+name+'/'+key+'.pgsg')
var rv = await verifyPgsg(JSON.parse(pgsg))
var serverName = rv[1]
assert(serverName.split('.').slice(-2).join('.') == 'amazonaws.com')
var clearText = rv[0]
//remove HTTP headers
var httpBody = clearText.split('\r\n\r\n').slice(1)
o[key] = {text:httpBody}
}
var rv = await check_oracle(o, true);
if (rv == true){
return {result:true, oracle:o};
}
return {result:false};
}
if (typeof module !== 'undefined'){ //we are in node.js environment
module.exports={
check_oracle,
oracle,
verifyOldOracle
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +0,0 @@
pgsg-node allows you to run PageSigner without the browser using nodejs
Install the dependencies:
npm install node-fetch asn1js pkijs universal-dom-parser @peculiar/webcrypto
NB! You must supply the file with HTTP headers with --headers path/to/headers
The most basic headers file looks like this:
GET /r/worldnews/ HTTP/1.1
Host: www.reddit.com <---first /r/n
<---second /r/n
Note that there are two carriage returns '/r/n/r/n' after the last header's last letter
Usage: pgsg-node <command> [option]
where <command> is one of notarize, verify, awscheck
Examples:
pgsg-node notarize example.com --headers headers.txt
Notarize example.com using HTTP headers from headers.txt
pgsg-node verify imported.pgsg
Verify a Pagesigner session from imported.pgsg. This will create a session directory with the decrypted cleartext and the copy of the pgsg file.
pgsg-node awscheck
Check that Pagesigner's oracle server is correctly set up. This check must be performed only once on the first use of pgsg-node. There is no need to perform the check more than once because the oracle server's parameters are hardcoded. Once the check completes successfully, the hardcoded parameters can be trusted for all future invocations of pgsg-node.

View File

@@ -1,3 +0,0 @@
GET /r/worldnews HTTP/1.1
Host: www.reddit.com

View File

@@ -1,240 +0,0 @@
#!/usr/bin/env node
//override pagesigner's global vars with nodejs ones
const { exit, argv, chdir, cwd } = require('process');
const path = require('path');
fetch = require('node-fetch');
asn1js = require("asn1js");
pkijs = require("pkijs");
DOMParser = require('universal-dom-parser');
const { Crypto } = require("@peculiar/webcrypto");
crypto = new Crypto();
pkijs.setEngine("newEngine", crypto, new pkijs.CryptoEngine({ name: "", crypto: crypto, subtle: crypto.subtle }))
const node_crypto = require('crypto');
const net = require('net');
const fs = require('fs');
const mainjs = require('../main.js');
const tlsn = require('../tlsn.js');
const utils = require('../tlsn_utils.js');
const socket = require('../socket.js');
const oracles = require('../oracles.js');
const verifychain = require('../verifychain/verifychain.js');
//make the functions callable without the prefix
ab2ba = utils.ab2ba
assert = utils.assert
ba2ab = utils.ba2ab
ba2int = utils.ba2int
ba2str = utils.ba2str
bi2ba = utils.bi2ba
b64encode = utils.b64encode
b64decode = utils.b64decode
b64urlencode = utils.b64urlencode
check_oracle = oracles.check_oracle
check_complete_records = socket.check_complete_records
checkCertSubjName = verifychain.checkCertSubjName
chosen_notary = oracles.oracle
computeCommitHash = tlsn.computeCommitHash
dechunk_http = utils.dechunk_http
decrypt_tls_responseV4 = tlsn.decrypt_tls_responseV4
eq = utils.eq
getCommonName = verifychain.getCommonName
getExpandedKeys = tlsn.getExpandedKeys
getModulus = verifychain.getModulus
getTime = utils.getTime
gunzip_http = utils.gunzip_http
oracle = oracles.oracle
parse_certs = verifychain.parse_certs
pem2ab = utils.pem2ab
pubkeyPEM2raw = utils.pubkeyPEM2raw
sha256 = utils.sha256
sigDER2p1363 = utils.sigDER2p1363
str2ba = utils.str2ba
wildTest = utils.wildTest
verifyChain = verifychain.verifyChain
verifyECParamsSig = tlsn.verifyECParamsSig
verifyNotarySig = tlsn.verifyNotarySig
verifyOldOracle = oracles.verifyOldOracle
verifyPgsg = mainjs.verifyPgsg
//override
getRandom = function(size){
return node_crypto.randomBytes(size).toJSON().data;
}
//override Socket
Socket = function(server, port){
this.server = server;
this.port = port;
this.sock = new net.Socket();
this.buf = [];
this.complete_records = []; //complete records
var parent = this
this.sock.on('data', function(d) {
//"this" resolves to net.Socket() not to Socket, that's why we use "parent"
var data = d.toJSON().data
parent.buf = [].concat(parent.buf, data)
var rv = check_complete_records(parent.buf);
parent.complete_records = [].concat(parent.complete_records, rv.comprecs);
if (!rv.is_complete) {
parent.buf = rv.incomprecs;
}
if (rv.is_complete){
parent.buf = []
}
console.log('Received data complete', parent.complete_records.length);
console.log('Received data incomplete', parent.buf.length);
});
}
Socket.prototype.constructor = Socket;
Socket.prototype.connect = async function() {
await this.sock.connect(this.port, this.server)
}
Socket.prototype.send = function(d) {
var data = new Buffer.from(d)
this.sock.write(data);
}
Socket.prototype.recv = async function(is_handshake) {
if (typeof(is_handshake) === 'undefined') {
is_handshake = false;
}
var that = this;
var resolved = false;
return await new Promise(function(resolve, reject){
var timer = setTimeout(function() {
resolved = true;
reject('recv: socket timed out');
}, 20*1000);
function finished_receiving() {
clearTimeout(timer);
console.log('recv promise resolving');
resolved = true;
resolve(that.complete_records);
//zero out the records because we're gonna be reusing this socket
that.complete_records = []
};
var check = function(){
if (resolved) {
return;
}
if (that.complete_records.length == 0 || that.buf.length > 0) {
console.log(that.complete_records.length, that.buf.length )
//either have not yet begun receiving of in the middle of receiving
setTimeout(function() {
check()
}, 100);
return;
}
if (that.complete_records.length > 0 && that.buf.length == 0) {
if (is_handshake){
finished_receiving();
return
}
//else give the server another second to send more data
setTimeout(function() {
if (that.buf.length === 0) {
finished_receiving();
return;
} else {
console.log('more data received after waiting for a second');
check();
}
}, 1000);
}
}
check();
});
}
//override
import_resource = async function(path){
//change to the PageSigner's base dir first
path = '../'+path
return fs.readFileSync(path).toString()
}
//override
Certificate = pkijs.Certificate;
CertificateChainValidationEngine = pkijs.CertificateChainValidationEngine
use_max_fragment_length = false;
//override
createNewSession = async function(creationTime, commonName, notaryName, cleartext, pgsg, is_imported){
var suffix = is_imported ? "_imported" : ""
var dirname = 'session_'+ creationTime + "_" + commonName + suffix
fs.mkdirSync(dirname)
fs.writeFileSync(path.join(__dirname, dirname, "cleartext"), cleartext)
fs.writeFileSync(path.join(__dirname, dirname, commonName+'.pgsg'), Buffer.from(JSON.stringify(pgsg)))
return dirname
}
function showUsage(){
console.log("Usage: pgsg-node <command> [option] \r\n")
console.log("where <command> is one of notarize, verify, awscheck\r\n")
console.log("Examples:\r\n")
console.log("pgsg-node notarize example.com --headers headers.txt")
console.log("Notarize example.com using HTTP headers from headers.txt\r\n")
console.log("pgsg-node verify imported.pgsg")
console.log("Verify a Pagesigner session from imported.pgsg. This will create a session directory with the decrypted cleartext and the copy of the pgsg file.\r\n")
console.log("pgsg-node awscheck")
console.log("Check that Pagesigner's oracle server is correctly set up. This check must be performed only once on the first use of pgsg-node. There is no need to perform the check more than once because the oracle server's parameters are hardcoded. Once the check completes successfully, the hardcoded parameters can be trusted for all future invocations of pgsg-node.")
console.log("\r\n")
exit()
}
async function main (){
if (argv[2] === 'awscheck') {
console.log('checking...may take up to 10 secs')
if (await check_oracle(oracles.oracle) != true){
console.log('verification failed')
}
console.log('verification successful')
exit()
}
if (argv[2] === 'notarize') {
if (argv.length !== 6 || (argv.length == 6 && argv[4] !== '--headers')){
showUsage();
}
var server = argv[3]
var headersfile = argv[5]
var headers = fs.readFileSync(headersfile).toString()
headers = headers.replace(/\n/g, '\r\n')
await verifychain.parse_certs()
var rv = await tlsn.start_audit(server, 443, headers)
var dirname = await mainjs.save_session(rv)
console.log('session saved in', dirname)
exit()
}
if (argv[2] === 'verify') {
if (argv.length !== 4){
showUsage()
}
var pgsgfile = argv[3]
var pgsgBuf = fs.readFileSync(pgsgfile)
console.log('pgsg.length', pgsgBuf.length)
var pgsg = JSON.parse(pgsgBuf)
await verifychain.parse_certs()
var rv = await mainjs.verifyPgsg(pgsg)
var server_name = rv[1]
var cleartext = rv[0]
var dirname = await createNewSession(getTime(), server_name, 'notary name', cleartext, pgsg, true)
console.log('session saved in', dirname)
exit()
}
showUsage()
}
main()

View File

@@ -1,153 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class AccessDescription
{
//**********************************************************************************
/**
* Constructor for AccessDescription class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc The type and format of the information are specified by the accessMethod field. This profile defines two accessMethod OIDs: id-ad-caIssuers and id-ad-ocsp
*/
this.accessMethod = getParametersValue(parameters, "accessMethod", AccessDescription.defaultValues("accessMethod"));
/**
* @type {GeneralName}
* @desc The accessLocation field specifies the location of the information
*/
this.accessLocation = getParametersValue(parameters, "accessLocation", AccessDescription.defaultValues("accessLocation"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "accessMethod":
return "";
case "accessLocation":
return new GeneralName();
default:
throw new Error(`Invalid member name for AccessDescription class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AccessDescription ::= SEQUENCE {
* accessMethod OBJECT IDENTIFIER,
* accessLocation GeneralName }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [accessMethod]
* @property {string} [accessLocation]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.accessMethod || "") }),
GeneralName.schema(names.accessLocation || {})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"accessMethod",
"accessLocation"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AccessDescription.schema({
names: {
accessMethod: "accessMethod",
accessLocation: {
names: {
blockName: "accessLocation"
}
}
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AccessDescription");
//endregion
//region Get internal properties from parsed schema
this.accessMethod = asn1.result.accessMethod.valueBlock.toString();
this.accessLocation = new GeneralName({ schema: asn1.result.accessLocation });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.accessMethod }),
this.accessLocation.toSchema()
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
accessMethod: this.accessMethod,
accessLocation: this.accessLocation.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,249 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC3161. Accuracy represents the time deviation around the UTC time contained in GeneralizedTime.
*/
export default class Accuracy
{
//**********************************************************************************
/**
* Constructor for Accuracy class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("seconds" in parameters)
/**
* @type {number}
* @desc seconds
*/
this.seconds = getParametersValue(parameters, "seconds", Accuracy.defaultValues("seconds"));
if("millis" in parameters)
/**
* @type {number}
* @desc millis
*/
this.millis = getParametersValue(parameters, "millis", Accuracy.defaultValues("millis"));
if("micros" in parameters)
/**
* @type {number}
* @desc micros
*/
this.micros = getParametersValue(parameters, "micros", Accuracy.defaultValues("micros"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "seconds":
case "millis":
case "micros":
return 0;
default:
throw new Error(`Invalid member name for Accuracy class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "seconds":
case "millis":
case "micros":
return (memberValue === Accuracy.defaultValues(memberName));
default:
throw new Error(`Invalid member name for Accuracy class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* Accuracy ::= SEQUENCE {
* seconds INTEGER OPTIONAL,
* millis [0] INTEGER (1..999) OPTIONAL,
* micros [1] INTEGER (1..999) OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [seconds]
* @property {string} [millis]
* @property {string} [micros]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
optional: true,
value: [
new asn1js.Integer({
optional: true,
name: (names.seconds || "")
}),
new asn1js.Primitive({
name: (names.millis || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
}
}),
new asn1js.Primitive({
name: (names.micros || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
}
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"seconds",
"millis",
"micros"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
Accuracy.schema({
names: {
seconds: "seconds",
millis: "millis",
micros: "micros"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for Accuracy");
//endregion
//region Get internal properties from parsed schema
if("seconds" in asn1.result)
this.seconds = asn1.result.seconds.valueBlock.valueDec;
if("millis" in asn1.result)
{
const intMillis = new asn1js.Integer({ valueHex: asn1.result.millis.valueBlock.valueHex });
this.millis = intMillis.valueBlock.valueDec;
}
if("micros" in asn1.result)
{
const intMicros = new asn1js.Integer({ valueHex: asn1.result.micros.valueBlock.valueHex });
this.micros = intMicros.valueBlock.valueDec;
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array of output sequence
const outputArray = [];
if("seconds" in this)
outputArray.push(new asn1js.Integer({ value: this.seconds }));
if("millis" in this)
{
const intMillis = new asn1js.Integer({ value: this.millis });
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
valueHex: intMillis.valueBlock.valueHex
}));
}
if("micros" in this)
{
const intMicros = new asn1js.Integer({ value: this.micros });
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
valueHex: intMicros.valueBlock.valueHex
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {};
if("seconds" in this)
_object.seconds = this.seconds;
if("millis" in this)
_object.millis = this.millis;
if("micros" in this)
_object.micros = this.micros;
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,212 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class AlgorithmIdentifier
{
//**********************************************************************************
/**
* Constructor for AlgorithmIdentifier class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
* @property {string} [algorithmId] ObjectIdentifier for algorithm (string representation)
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc ObjectIdentifier for algorithm (string representation)
*/
this.algorithmId = getParametersValue(parameters, "algorithmId", AlgorithmIdentifier.defaultValues("algorithmId"));
if("algorithmParams" in parameters)
/**
* @type {Object}
* @desc Any algorithm parameters
*/
this.algorithmParams = getParametersValue(parameters, "algorithmParams", AlgorithmIdentifier.defaultValues("algorithmParams"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "algorithmId":
return "";
case "algorithmParams":
return new asn1js.Any();
default:
throw new Error(`Invalid member name for AlgorithmIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "algorithmId":
return (memberValue === "");
case "algorithmParams":
return (memberValue instanceof asn1js.Any);
default:
throw new Error(`Invalid member name for AlgorithmIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AlgorithmIdentifier ::= Sequence {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} algorithmIdentifier ObjectIdentifier for the algorithm
* @property {string} algorithmParams Any algorithm parameters
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
optional: (names.optional || false),
value: [
new asn1js.ObjectIdentifier({ name: (names.algorithmIdentifier || "") }),
new asn1js.Any({ name: (names.algorithmParams || ""), optional: true })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"algorithm",
"params"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AlgorithmIdentifier.schema({
names: {
algorithmIdentifier: "algorithm",
algorithmParams: "params"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AlgorithmIdentifier");
//endregion
//region Get internal properties from parsed schema
this.algorithmId = asn1.result.algorithm.valueBlock.toString();
if("params" in asn1.result)
this.algorithmParams = asn1.result.params;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.algorithmId }));
if(("algorithmParams" in this) && ((this.algorithmParams instanceof asn1js.Any) === false))
outputArray.push(this.algorithmParams);
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
algorithmId: this.algorithmId
};
if(("algorithmParams" in this) && ((this.algorithmParams instanceof asn1js.Any) === false))
object.algorithmParams = this.algorithmParams.toJSON();
return object;
}
//**********************************************************************************
/**
* Check that two "AlgorithmIdentifiers" are equal
* @param {AlgorithmIdentifier} algorithmIdentifier
* @returns {boolean}
*/
isEqual(algorithmIdentifier)
{
//region Check input type
if((algorithmIdentifier instanceof AlgorithmIdentifier) === false)
return false;
//endregion
//region Check "algorithm_id"
if(this.algorithmId !== algorithmIdentifier.algorithmId)
return false;
//endregion
//region Check "algorithm_params"
if("algorithmParams" in this)
{
if("algorithmParams" in algorithmIdentifier)
return JSON.stringify(this.algorithmParams) === JSON.stringify(algorithmIdentifier.algorithmParams);
return false;
}
if("algorithmParams" in algorithmIdentifier)
return false;
//endregion
return true;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,135 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class AltName
{
//**********************************************************************************
/**
* Constructor for AltName class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<GeneralName>}
* @desc Array of alternative names in GeneralName type
*/
this.altNames = getParametersValue(parameters, "altNames", AltName.defaultValues("altNames"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "altNames":
return [];
default:
throw new Error(`Invalid member name for AltName class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AltName ::= GeneralNames
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [altNames]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.altNames || ""),
value: GeneralName.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"altNames"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AltName.schema({
names: {
altNames: "altNames"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AltName");
//endregion
//region Get internal properties from parsed schema
if("altNames" in asn1.result)
this.altNames = Array.from(asn1.result.altNames, element => new GeneralName({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.altNames, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
altNames: Array.from(this.altNames, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,177 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC2986
*/
export default class Attribute {
//**********************************************************************************
/**
* Constructor for Attribute class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc ObjectIdentifier for attribute (string representation)
*/
this.type = getParametersValue(parameters, "type", Attribute.defaultValues("type"));
/**
* @type {Array}
* @desc Any attribute values
*/
this.values = getParametersValue(parameters, "values", Attribute.defaultValues("values"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "type":
return "";
case "values":
return [];
default:
throw new Error(`Invalid member name for Attribute class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "type":
return (memberValue === "");
case "values":
return (memberValue.length === 0);
default:
throw new Error(`Invalid member name for Attribute class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
* type ATTRIBUTE.&id({IOSet}),
* values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [type]
* @property {string} [setName]
* @property {string} [values]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.type || "") }),
new asn1js.Set({
name: (names.setName || ""),
value: [
new asn1js.Repeated({
name: (names.values || ""),
value: new asn1js.Any()
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"type",
"values"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
Attribute.schema({
names: {
type: "type",
values: "values"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for Attribute");
//endregion
//region Get internal properties from parsed schema
this.type = asn1.result.type.valueBlock.toString();
this.values = asn1.result.values;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.type }),
new asn1js.Set({
value: this.values
})
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
type: this.type,
values: Array.from(this.values, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,871 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralNames from "./GeneralNames.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import Attribute from "./Attribute.js";
import Extensions from "./Extensions.js";
//**************************************************************************************
/**
* Class from RFC5755
*/
export class AttCertValidityPeriod
{
//**********************************************************************************
/**
* Constructor for AttCertValidityPeriod class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {GeneralizedTime}
* @desc notBeforeTime
*/
this.notBeforeTime = getParametersValue(parameters, "notBeforeTime", AttCertValidityPeriod.defaultValues("notBeforeTime"));
/**
* @type {GeneralizedTime}
* @desc notAfterTime
*/
this.notAfterTime = getParametersValue(parameters, "notAfterTime", AttCertValidityPeriod.defaultValues("notAfterTime"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "notBeforeTime":
case "notAfterTime":
return new Date(0, 0, 0);
default:
throw new Error(`Invalid member name for AttCertValidityPeriod class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AttCertValidityPeriod ::= SEQUENCE {
* notBeforeTime GeneralizedTime,
* notAfterTime GeneralizedTime
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [notBeforeTime]
* @property {string} [notAfterTime]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.GeneralizedTime({ name: (names.notBeforeTime || "") }),
new asn1js.GeneralizedTime({ name: (names.notAfterTime || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"notBeforeTime",
"notAfterTime"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AttCertValidityPeriod.schema({
names: {
notBeforeTime: "notBeforeTime",
notAfterTime: "notAfterTime"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AttCertValidityPeriod");
//endregion
//region Get internal properties from parsed schema
this.notBeforeTime = asn1.result.notBeforeTime.toDate();
this.notAfterTime = asn1.result.notAfterTime.toDate();
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.GeneralizedTime({ valueDate: this.notBeforeTime }),
new asn1js.GeneralizedTime({ valueDate: this.notAfterTime }),
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
notBeforeTime: this.notBeforeTime,
notAfterTime: this.notAfterTime
};
}
//**********************************************************************************
}
//**************************************************************************************
/**
* Class from RFC5755
*/
export class IssuerSerial
{
//**********************************************************************************
/**
* Constructor for IssuerSerial class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {RelativeDistinguishedNames}
* @desc issuer
*/
this.issuer = getParametersValue(parameters, "issuer", IssuerSerial.defaultValues("issuer"));
/**
* @type {Integer}
* @desc serialNumber
*/
this.serialNumber = getParametersValue(parameters, "serialNumber", IssuerSerial.defaultValues("serialNumber"));
if("issuerUID" in parameters)
/**
* @type {BitString}
* @desc issuerUID
*/
this.issuerUID = getParametersValue(parameters, "issuerUID", IssuerSerial.defaultValues("issuerUID"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "issuer":
return new GeneralNames();
case "serialNumber":
return new asn1js.Integer();
case "issuerUID":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for IssuerSerial class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* IssuerSerial ::= SEQUENCE {
* issuer GeneralNames,
* serial CertificateSerialNumber,
* issuerUID UniqueIdentifier OPTIONAL
* }
*
* CertificateSerialNumber ::= INTEGER
* UniqueIdentifier ::= BIT STRING
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [issuer]
* @property {string} [serialNumber]
* @property {string} [issuerUID]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
GeneralNames.schema(names.issuer || {}),
new asn1js.Integer({ name: (names.serialNumber || "") }),
new asn1js.BitString({
optional: true,
name: (names.issuerUID || "")
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"issuer",
"serialNumber",
"issuerUID"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
IssuerSerial.schema({
names: {
issuer: {
names: {
blockName: "issuer"
}
},
serialNumber: "serialNumber",
issuerUID: "issuerUID"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for IssuerSerial");
//endregion
//region Get internal properties from parsed schema
this.issuer = new GeneralNames({ schema: asn1.result.issuer });
this.serialNumber = asn1.result.serialNumber;
if("issuerUID" in asn1.result)
this.issuerUID = asn1.result.issuerUID;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
const result = new asn1js.Sequence({
value: [
this.issuer.toSchema(),
this.serialNumber
]
});
if("issuerUID" in this)
result.valueBlock.value.push(this.issuerUID);
//region Construct and return new ASN.1 schema for this object
return result;
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const result = {
issuer: this.issuer.toJSON(),
serialNumber: this.serialNumber.toJSON()
};
if("issuerUID" in this)
result.issuerUID = this.issuerUID.toJSON();
return result;
}
//**********************************************************************************
}
//**************************************************************************************
/**
* Class from RFC5755
*/
export class AttributeCertificateInfoV1
{
//**********************************************************************************
/**
* Constructor for AttributeCertificateInfoV1 class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", AttributeCertificateInfoV1.defaultValues("version"));
if("baseCertificateID" in parameters)
/**
* @type {IssuerSerial}
* @desc baseCertificateID
*/
this.baseCertificateID = getParametersValue(parameters, "baseCertificateID", AttributeCertificateInfoV1.defaultValues("baseCertificateID"));
if("subjectName" in parameters)
/**
* @type {GeneralNames}
* @desc subjectName
*/
this.subjectName = getParametersValue(parameters, "subjectName", AttributeCertificateInfoV1.defaultValues("subjectName"));
/**
* @type {GeneralNames}
* @desc issuer
*/
this.issuer = getParametersValue(parameters, "issuer", AttributeCertificateInfoV1.defaultValues("issuer"));
/**
* @type {AlgorithmIdentifier}
* @desc signature
*/
this.signature = getParametersValue(parameters, "signature", AttributeCertificateInfoV1.defaultValues("signature"));
/**
* @type {Integer}
* @desc serialNumber
*/
this.serialNumber = getParametersValue(parameters, "serialNumber", AttributeCertificateInfoV1.defaultValues("serialNumber"));
/**
* @type {AttCertValidityPeriod}
* @desc attrCertValidityPeriod
*/
this.attrCertValidityPeriod = getParametersValue(parameters, "attrCertValidityPeriod", AttributeCertificateInfoV1.defaultValues("attrCertValidityPeriod"));
/**
* @type {Array.<Attribute>}
* @desc attributes
*/
this.attributes = getParametersValue(parameters, "attributes", AttributeCertificateInfoV1.defaultValues("attributes"));
if("issuerUniqueID" in parameters)
/**
* @type {BitString}
* @desc issuerUniqueID
*/
this.issuerUniqueID = getParametersValue(parameters, "issuerUniqueID", AttributeCertificateInfoV1.defaultValues("issuerUniqueID"));
if("extensions" in parameters)
/**
* @type {Extensions}
* @desc extensions
*/
this.extensions = getParametersValue(parameters, "extensions", AttributeCertificateInfoV1.defaultValues("extensions"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return 0;
case "baseCertificateID":
return new IssuerSerial();
case "subjectName":
return new GeneralNames();
case "issuer":
return {};
case "signature":
return new AlgorithmIdentifier();
case "serialNumber":
return new asn1js.Integer();
case "attrCertValidityPeriod":
return new AttCertValidityPeriod();
case "attributes":
return [];
case "issuerUniqueID":
return new asn1js.BitString();
case "extensions":
return new Extensions();
default:
throw new Error(`Invalid member name for AttributeCertificateInfoV1 class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AttributeCertificateInfo ::= SEQUENCE {
* version Version DEFAULT v1,
* subject CHOICE {
* baseCertificateID [0] IssuerSerial, -- associated with a Public Key Certificate
* subjectName [1] GeneralNames }, -- associated with a name
* issuer GeneralNames, -- CA issuing the attribute certificate
* signature AlgorithmIdentifier,
* serialNumber CertificateSerialNumber,
* attrCertValidityPeriod AttCertValidityPeriod,
* attributes SEQUENCE OF Attribute,
* issuerUniqueID UniqueIdentifier OPTIONAL,
* extensions Extensions OPTIONAL
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [issuer]
* @property {string} [serialNumber]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Integer({ name: (names.version || "") }),
new asn1js.Choice({
value: [
new asn1js.Constructed({
name: (names.baseCertificateID || ""),
idBlock: {
tagClass: 3,
tagNumber: 0 // [0]
},
value: IssuerSerial.schema().valueBlock.value
}),
new asn1js.Constructed({
name: (names.subjectName || ""),
idBlock: {
tagClass: 3,
tagNumber: 1 // [2]
},
value: GeneralNames.schema().valueBlock.value
}),
]
}),
GeneralNames.schema({
names: {
blockName: (names.issuer || "")
}
}),
AlgorithmIdentifier.schema(names.signature || {}),
new asn1js.Integer({ name: (names.serialNumber || "") }),
AttCertValidityPeriod.schema(names.attrCertValidityPeriod || {}),
new asn1js.Sequence({
name: (names.attributes || ""),
value: [
new asn1js.Repeated({
value: Attribute.schema()
})
]
}),
new asn1js.BitString({
optional: true,
name: (names.issuerUniqueID || "")
}),
Extensions.schema(names.extensions || {}, true)
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"baseCertificateID",
"subjectName",
"issuer",
"signature",
"serialNumber",
"attrCertValidityPeriod",
"attributes",
"issuerUniqueID",
"extensions"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AttributeCertificateInfoV1.schema({
names: {
version: "version",
baseCertificateID: "baseCertificateID",
subjectName: "subjectName",
issuer: "issuer",
signature: {
names: {
blockName: "signature"
}
},
serialNumber: "serialNumber",
attrCertValidityPeriod: {
names: {
blockName: "attrCertValidityPeriod"
}
},
attributes: "attributes",
issuerUniqueID: "issuerUniqueID",
extensions: {
names: {
blockName: "extensions"
}
}
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AttributeCertificateInfoV1");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
if("baseCertificateID" in asn1.result)
{
this.baseCertificateID = new IssuerSerial({
schema: new asn1js.Sequence({
value: asn1.result.baseCertificateID.valueBlock.value
})
});
}
if("subjectName" in asn1.result)
{
this.subjectName = new GeneralNames({
schema: new asn1js.Sequence({
value: asn1.result.subjectName.valueBlock.value
})
});
}
this.issuer = asn1.result.issuer;
this.signature = new AlgorithmIdentifier({ schema: asn1.result.signature });
this.serialNumber = asn1.result.serialNumber;
this.attrCertValidityPeriod = new AttCertValidityPeriod({ schema: asn1.result.attrCertValidityPeriod });
this.attributes = Array.from(asn1.result.attributes.valueBlock.value, element => new Attribute({ schema: element }));
if("issuerUniqueID" in asn1.result)
this.issuerUniqueID = asn1.result.issuerUniqueID;
if("extensions" in asn1.result)
this.extensions = new Extensions({ schema: asn1.result.extensions });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
const result = new asn1js.Sequence({
value: [new asn1js.Integer({ value: this.version })]
});
if("baseCertificateID" in this)
{
result.valueBlock.value.push(new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: 0 // [0]
},
value: this.baseCertificateID.toSchema().valueBlock.value
}));
}
if("subjectName" in this)
{
result.valueBlock.value.push(new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: 1 // [1]
},
value: this.subjectName.toSchema().valueBlock.value
}));
}
result.valueBlock.value.push(this.issuer.toSchema());
result.valueBlock.value.push(this.signature.toSchema());
result.valueBlock.value.push(this.serialNumber);
result.valueBlock.value.push(this.attrCertValidityPeriod.toSchema());
result.valueBlock.value.push(new asn1js.Sequence({
value: Array.from(this.attributes, element => element.toSchema())
}));
if("issuerUniqueID" in this)
result.valueBlock.value.push(this.issuerUniqueID);
if("extensions" in this)
result.valueBlock.value.push(this.extensions.toSchema());
return result;
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const result = {
version: this.version
};
if("baseCertificateID" in this)
result.baseCertificateID = this.baseCertificateID.toJSON();
if("subjectName" in this)
result.subjectName = this.subjectName.toJSON();
result.issuer = this.issuer.toJSON();
result.signature = this.signature.toJSON();
result.serialNumber = this.serialNumber.toJSON();
result.attrCertValidityPeriod = this.attrCertValidityPeriod.toJSON();
result.attributes = Array.from(this.attributes, element => element.toJSON());
if("issuerUniqueID" in this)
result.issuerUniqueID = this.issuerUniqueID.toJSON();
if("extensions" in this)
result.extensions = this.extensions.toJSON();
return result;
}
//**********************************************************************************
}
//**************************************************************************************
/**
* Class from X.509:1997
*/
export default class AttributeCertificateV1
{
//**********************************************************************************
/**
* Constructor for AttributeCertificateV1 class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AttributeCertificateInfoV1}
* @desc acinfo
*/
this.acinfo = getParametersValue(parameters, "acinfo", AttributeCertificateV1.defaultValues("acinfo"));
/**
* @type {AlgorithmIdentifier}
* @desc signatureAlgorithm
*/
this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", AttributeCertificateV1.defaultValues("signatureAlgorithm"));
/**
* @type {BitString}
* @desc signatureValue
*/
this.signatureValue = getParametersValue(parameters, "signatureValue", AttributeCertificateV1.defaultValues("signatureValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "acinfo":
return new AttributeCertificateInfoV1();
case "signatureAlgorithm":
return new AlgorithmIdentifier();
case "signatureValue":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for AttributeCertificateV1 class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AttributeCertificate ::= SEQUENCE {
* acinfo AttributeCertificateInfoV1,
* signatureAlgorithm AlgorithmIdentifier,
* signatureValue BIT STRING
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {Object} [acinfo]
* @property {Object} [signatureAlgorithm]
* @property {string} [signatureValue]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AttributeCertificateInfoV1.schema(names.acinfo || {}),
AlgorithmIdentifier.schema(names.signatureAlgorithm || {}),
new asn1js.BitString({ name: (names.signatureValue || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"acinfo",
"signatureValue",
"signatureAlgorithm"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AttributeCertificateV1.schema({
names: {
acinfo: {
names: {
blockName: "acinfo"
}
},
signatureAlgorithm: {
names: {
blockName: "signatureAlgorithm"
}
},
signatureValue: "signatureValue"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AttributeCertificateV1");
//endregion
//region Get internal properties from parsed schema
this.acinfo = new AttributeCertificateInfoV1({ schema: asn1.result.acinfo });
this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
this.signatureValue = asn1.result.signatureValue;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
return (new asn1js.Sequence({
value: [
this.acinfo.toSchema(),
this.signatureAlgorithm.toSchema(),
this.signatureValue
]
}));
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
acinfo: this.acinfo.toJSON(),
signatureAlgorithm: this.signatureAlgorithm.toJSON(),
signatureValue: this.signatureValue.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -1,232 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, isEqualBuffer, clearProps } from "./pvutils.js";
import { stringPrep } from "./common.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class AttributeTypeAndValue
{
//**********************************************************************************
/**
* Constructor for AttributeTypeAndValue class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc type
*/
this.type = getParametersValue(parameters, "type", AttributeTypeAndValue.defaultValues("type"));
/**
* @type {Object}
* @desc Value of the AttributeTypeAndValue class
*/
this.value = getParametersValue(parameters, "value", AttributeTypeAndValue.defaultValues("value"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "type":
return "";
case "value":
return {};
default:
throw new Error(`Invalid member name for AttributeTypeAndValue class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AttributeTypeAndValue ::= Sequence {
* type AttributeType,
* value AttributeValue }
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY -- DEFINED BY AttributeType
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName] Name for entire block
* @property {string} [type] Name for "type" element
* @property {string} [value] Name for "value" element
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.type || "") }),
new asn1js.Any({ name: (names.value || "") })
]
}));
}
//**********************************************************************************
static blockName()
{
return "AttributeTypeAndValue";
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"type",
"typeValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AttributeTypeAndValue.schema({
names: {
type: "type",
value: "typeValue"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AttributeTypeAndValue");
//endregion
//region Get internal properties from parsed schema
this.type = asn1.result.type.valueBlock.toString();
// noinspection JSUnresolvedVariable
this.value = asn1.result.typeValue;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.type }),
this.value
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
type: this.type
};
if(Object.keys(this.value).length !== 0)
_object.value = this.value.toJSON();
else
_object.value = this.value;
return _object;
}
//**********************************************************************************
/**
* Compare two AttributeTypeAndValue values, or AttributeTypeAndValue with ArrayBuffer value
* @param {(AttributeTypeAndValue|ArrayBuffer)} compareTo The value compare to current
* @returns {boolean}
*/
isEqual(compareTo)
{
const stringBlockNames = [
asn1js.Utf8String.blockName(),
asn1js.BmpString.blockName(),
asn1js.UniversalString.blockName(),
asn1js.NumericString.blockName(),
asn1js.PrintableString.blockName(),
asn1js.TeletexString.blockName(),
asn1js.VideotexString.blockName(),
asn1js.IA5String.blockName(),
asn1js.GraphicString.blockName(),
asn1js.VisibleString.blockName(),
asn1js.GeneralString.blockName(),
asn1js.CharacterString.blockName()
];
if(compareTo.constructor.blockName() === AttributeTypeAndValue.blockName())
{
if(this.type !== compareTo.type)
return false;
//region Check we do have both strings
let isString = false;
const thisName = this.value.constructor.blockName();
if(thisName === compareTo.value.constructor.blockName())
{
for(const name of stringBlockNames)
{
if(thisName === name)
{
isString = true;
break;
}
}
}
//endregion
if(isString)
{
const value1 = stringPrep(this.value.valueBlock.value);
const value2 = stringPrep(compareTo.value.valueBlock.value);
if(value1.localeCompare(value2) !== 0)
return false;
}
else // Comparing as two ArrayBuffers
{
if(isEqualBuffer(this.value.valueBeforeDecode, compareTo.value.valueBeforeDecode) === false)
return false;
}
return true;
}
if(compareTo instanceof ArrayBuffer)
return isEqualBuffer(this.value.valueBeforeDecode, compareTo);
return false;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,513 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, utilConcatBuf, clearProps } from "./pvutils.js";
import ContentInfo from "./ContentInfo.js";
import SafeContents from "./SafeContents.js";
import EnvelopedData from "./EnvelopedData.js";
import EncryptedData from "./EncryptedData.js";
//**************************************************************************************
/**
* Class from RFC7292
*/
export default class AuthenticatedSafe
{
//**********************************************************************************
/**
* Constructor for AuthenticatedSafe class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<ContentInfo>}
* @desc safeContents
*/
this.safeContents = getParametersValue(parameters, "safeContents", AuthenticatedSafe.defaultValues("safeContents"));
if("parsedValue" in parameters)
/**
* @type {*}
* @desc parsedValue
*/
this.parsedValue = getParametersValue(parameters, "parsedValue", AuthenticatedSafe.defaultValues("parsedValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "safeContents":
return [];
case "parsedValue":
return {};
default:
throw new Error(`Invalid member name for AuthenticatedSafe class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "safeContents":
return (memberValue.length === 0);
case "parsedValue":
return ((memberValue instanceof Object) && (Object.keys(memberValue).length === 0));
default:
throw new Error(`Invalid member name for AuthenticatedSafe class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AuthenticatedSafe ::= SEQUENCE OF ContentInfo
* -- Data if unencrypted
* -- EncryptedData if password-encrypted
* -- EnvelopedData if public key-encrypted
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [contentInfos]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.contentInfos || ""),
value: ContentInfo.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"contentInfos"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AuthenticatedSafe.schema({
names: {
contentInfos: "contentInfos"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AuthenticatedSafe");
//endregion
//region Get internal properties from parsed schema
this.safeContents = Array.from(asn1.result.contentInfos, element => new ContentInfo({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.safeContents, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
safeContents: Array.from(this.safeContents, element => element.toJSON())
};
}
//**********************************************************************************
parseInternalValues(parameters)
{
//region Check input data from "parameters"
if((parameters instanceof Object) === false)
return Promise.reject("The \"parameters\" must has \"Object\" type");
if(("safeContents" in parameters) === false)
return Promise.reject("Absent mandatory parameter \"safeContents\"");
if((parameters.safeContents instanceof Array) === false)
return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type");
if(parameters.safeContents.length !== this.safeContents.length)
return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.safeContents.length\"");
//endregion
//region Initial variables
let sequence = Promise.resolve();
//endregion
//region Create value for "this.parsedValue.authenticatedSafe"
this.parsedValue = {
safeContents: []
};
for(const [index, content] of this.safeContents.entries())
{
switch(content.contentType)
{
//region data
case "1.2.840.113549.1.7.1":
{
//region Check that we do have OCTETSTRING as "content"
if((content.content instanceof asn1js.OctetString) === false)
return Promise.reject("Wrong type of \"this.safeContents[j].content\"");
//endregion
//region Check we have "constructive encoding" for AuthSafe content
let authSafeContent = new ArrayBuffer(0);
if(content.content.valueBlock.isConstructed)
{
for(const contentValue of content.content.valueBlock.value)
authSafeContent = utilConcatBuf(authSafeContent, contentValue.valueBlock.valueHex);
}
else
authSafeContent = content.content.valueBlock.valueHex;
//endregion
//region Parse internal ASN.1 data
const asn1 = asn1js.fromBER(authSafeContent);
if(asn1.offset === (-1))
return Promise.reject("Error during parsing of ASN.1 data inside \"content.content\"");
//endregion
//region Finilly initialize initial values of "SafeContents" type
this.parsedValue.safeContents.push({
privacyMode: 0, // No privacy, clear data
value: new SafeContents({ schema: asn1.result })
});
//endregion
}
break;
//endregion
//region envelopedData
case "1.2.840.113549.1.7.3":
{
//region Initial variables
const cmsEnveloped = new EnvelopedData({ schema: content.content });
//endregion
//region Check mandatory parameters
if(("recipientCertificate" in parameters.safeContents[index]) === false)
return Promise.reject("Absent mandatory parameter \"recipientCertificate\" in \"parameters.safeContents[j]\"");
const recipientCertificate = parameters.safeContents[index].recipientCertificate;
if(("recipientKey" in parameters.safeContents[index]) === false)
return Promise.reject("Absent mandatory parameter \"recipientKey\" in \"parameters.safeContents[j]\"");
// noinspection JSUnresolvedVariable
const recipientKey = parameters.safeContents[index].recipientKey;
//endregion
//region Decrypt CMS EnvelopedData using first recipient information
sequence = sequence.then(
() => cmsEnveloped.decrypt(0, {
recipientCertificate,
recipientPrivateKey: recipientKey
})
);
sequence = sequence.then(
/**
* @param {ArrayBuffer} result
*/
result =>
{
const asn1 = asn1js.fromBER(result);
if(asn1.offset === (-1))
return Promise.reject("Error during parsing of decrypted data");
this.parsedValue.safeContents.push({
privacyMode: 2, // Public-key privacy mode
value: new SafeContents({ schema: asn1.result })
});
return Promise.resolve();
}
);
//endregion
}
break;
//endregion
//region encryptedData
case "1.2.840.113549.1.7.6":
{
//region Initial variables
const cmsEncrypted = new EncryptedData({ schema: content.content });
//endregion
//region Check mandatory parameters
if(("password" in parameters.safeContents[index]) === false)
return Promise.reject("Absent mandatory parameter \"password\" in \"parameters.safeContents[j]\"");
const password = parameters.safeContents[index].password;
//endregion
//region Decrypt CMS EncryptedData using password
sequence = sequence.then(
() => cmsEncrypted.decrypt({
password
}),
error => Promise.reject(error)
);
//endregion
//region Initialize internal data
sequence = sequence.then(
/**
* @param {ArrayBuffer} result
*/
result =>
{
const asn1 = asn1js.fromBER(result);
if(asn1.offset === (-1))
return Promise.reject("Error during parsing of decrypted data");
this.parsedValue.safeContents.push({
privacyMode: 1, // Password-based privacy mode
value: new SafeContents({ schema: asn1.result })
});
return Promise.resolve();
},
error => Promise.reject(error)
);
//endregion
}
break;
//endregion
//region default
default:
throw new Error(`Unknown "contentType" for AuthenticatedSafe: " ${content.contentType}`);
//endregion
}
}
//endregion
return sequence;
}
//**********************************************************************************
makeInternalValues(parameters)
{
//region Check data in "parsedValue"
if(("parsedValue" in this) === false)
return Promise.reject("Please run \"parseValues\" first or add \"parsedValue\" manually");
if((this.parsedValue instanceof Object) === false)
return Promise.reject("The \"this.parsedValue\" must has \"Object\" type");
if((this.parsedValue.safeContents instanceof Array) === false)
return Promise.reject("The \"this.parsedValue.safeContents\" must has \"Array\" type");
//endregion
//region Check input data from "parameters"
if((parameters instanceof Object) === false)
return Promise.reject("The \"parameters\" must has \"Object\" type");
if(("safeContents" in parameters) === false)
return Promise.reject("Absent mandatory parameter \"safeContents\"");
if((parameters.safeContents instanceof Array) === false)
return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type");
if(parameters.safeContents.length !== this.parsedValue.safeContents.length)
return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.parsedValue.safeContents\"");
//endregion
//region Initial variables
let sequence = Promise.resolve();
//endregion
//region Create internal values from already parsed values
this.safeContents = [];
for(const [index, content] of this.parsedValue.safeContents.entries())
{
//region Check current "content" value
if(("privacyMode" in content) === false)
return Promise.reject("The \"privacyMode\" is a mandatory parameter for \"content\"");
if(("value" in content) === false)
return Promise.reject("The \"value\" is a mandatory parameter for \"content\"");
if((content.value instanceof SafeContents) === false)
return Promise.reject("The \"content.value\" must has \"SafeContents\" type");
//endregion
switch(content.privacyMode)
{
//region No privacy
case 0:
{
const contentBuffer = content.value.toSchema().toBER(false);
sequence = sequence.then(
() =>
{
this.safeContents.push(new ContentInfo({
contentType: "1.2.840.113549.1.7.1",
content: new asn1js.OctetString({ valueHex: contentBuffer })
}));
});
}
break;
//endregion
//region Privacy with password
case 1:
{
//region Initial variables
const cmsEncrypted = new EncryptedData();
const currentParameters = parameters.safeContents[index];
currentParameters.contentToEncrypt = content.value.toSchema().toBER(false);
//endregion
//region Encrypt CMS EncryptedData using password
sequence = sequence.then(
() => cmsEncrypted.encrypt(currentParameters),
error => Promise.reject(error)
);
//endregion
//region Store result content in CMS_CONTENT_INFO type
sequence = sequence.then(
() =>
{
this.safeContents.push(new ContentInfo({
contentType: "1.2.840.113549.1.7.6",
content: cmsEncrypted.toSchema()
}));
},
error => Promise.reject(error)
);
//endregion
}
break;
//endregion
//region Privacy with public key
case 2:
{
//region Initial variables
const cmsEnveloped = new EnvelopedData();
const contentToEncrypt = content.value.toSchema().toBER(false);
//endregion
//region Check mandatory parameters
if(("encryptingCertificate" in parameters.safeContents[index]) === false)
return Promise.reject("Absent mandatory parameter \"encryptingCertificate\" in \"parameters.safeContents[i]\"");
if(("encryptionAlgorithm" in parameters.safeContents[index]) === false)
return Promise.reject("Absent mandatory parameter \"encryptionAlgorithm\" in \"parameters.safeContents[i]\"");
switch(true)
{
case (parameters.safeContents[index].encryptionAlgorithm.name.toLowerCase() === "aes-cbc"):
case (parameters.safeContents[index].encryptionAlgorithm.name.toLowerCase() === "aes-gcm"):
break;
default:
return Promise.reject(`Incorrect parameter "encryptionAlgorithm" in "parameters.safeContents[i]": ${parameters.safeContents[index].encryptionAlgorithm}`);
}
switch(true)
{
case (parameters.safeContents[index].encryptionAlgorithm.length === 128):
case (parameters.safeContents[index].encryptionAlgorithm.length === 192):
case (parameters.safeContents[index].encryptionAlgorithm.length === 256):
break;
default:
return Promise.reject(`Incorrect parameter "encryptionAlgorithm.length" in "parameters.safeContents[i]": ${parameters.safeContents[index].encryptionAlgorithm.length}`);
}
//endregion
//region Making correct "encryptionAlgorithm" variable
const encryptionAlgorithm = parameters.safeContents[index].encryptionAlgorithm;
//endregion
//region Append recipient for enveloped data
cmsEnveloped.addRecipientByCertificate(parameters.safeContents[index].encryptingCertificate);
//endregion
//region Making encryption
sequence = sequence.then(
() => cmsEnveloped.encrypt(encryptionAlgorithm, contentToEncrypt)
);
sequence = sequence.then(
() =>
{
this.safeContents.push(new ContentInfo({
contentType: "1.2.840.113549.1.7.3",
content: cmsEnveloped.toSchema()
}));
}
);
//endregion
}
break;
//endregion
//region default
default:
return Promise.reject(`Incorrect value for "content.privacyMode": ${content.privacyMode}`);
//endregion
}
}
//endregion
//region Return result of the function
return sequence.then(
() => this,
error => Promise.reject(`Error during parsing: ${error}`)
);
//endregion
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,244 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class AuthorityKeyIdentifier
{
//**********************************************************************************
/**
* Constructor for AuthorityKeyIdentifier class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("keyIdentifier" in parameters)
/**
* @type {OctetString}
* @desc keyIdentifier
*/
this.keyIdentifier = getParametersValue(parameters, "keyIdentifier", AuthorityKeyIdentifier.defaultValues("keyIdentifier"));
if("authorityCertIssuer" in parameters)
/**
* @type {Array.<GeneralName>}
* @desc authorityCertIssuer
*/
this.authorityCertIssuer = getParametersValue(parameters, "authorityCertIssuer", AuthorityKeyIdentifier.defaultValues("authorityCertIssuer"));
if("authorityCertSerialNumber" in parameters)
/**
* @type {Integer}
* @desc authorityCertIssuer
*/
this.authorityCertSerialNumber = getParametersValue(parameters, "authorityCertSerialNumber", AuthorityKeyIdentifier.defaultValues("authorityCertSerialNumber"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "keyIdentifier":
return new asn1js.OctetString();
case "authorityCertIssuer":
return [];
case "authorityCertSerialNumber":
return new asn1js.Integer();
default:
throw new Error(`Invalid member name for AuthorityKeyIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AuthorityKeyIdentifier OID ::= 2.5.29.35
*
* AuthorityKeyIdentifier ::= SEQUENCE {
* keyIdentifier [0] KeyIdentifier OPTIONAL,
* authorityCertIssuer [1] GeneralNames OPTIONAL,
* authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
*
* KeyIdentifier ::= OCTET STRING
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [keyIdentifier]
* @property {string} [authorityCertIssuer]
* @property {string} [authorityCertSerialNumber]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Primitive({
name: (names.keyIdentifier || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
}
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.Repeated({
name: (names.authorityCertIssuer || ""),
value: GeneralName.schema()
})
]
}),
new asn1js.Primitive({
name: (names.authorityCertSerialNumber || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
}
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"keyIdentifier",
"authorityCertIssuer",
"authorityCertSerialNumber"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
AuthorityKeyIdentifier.schema({
names: {
keyIdentifier: "keyIdentifier",
authorityCertIssuer: "authorityCertIssuer",
authorityCertSerialNumber: "authorityCertSerialNumber"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for AuthorityKeyIdentifier");
//endregion
//region Get internal properties from parsed schema
if("keyIdentifier" in asn1.result)
this.keyIdentifier = new asn1js.OctetString({ valueHex: asn1.result.keyIdentifier.valueBlock.valueHex });
if("authorityCertIssuer" in asn1.result)
this.authorityCertIssuer = Array.from(asn1.result.authorityCertIssuer, element => new GeneralName({ schema: element }));
if("authorityCertSerialNumber" in asn1.result)
this.authorityCertSerialNumber = new asn1js.Integer({ valueHex: asn1.result.authorityCertSerialNumber.valueBlock.valueHex });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if("keyIdentifier" in this)
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
valueHex: this.keyIdentifier.valueBlock.valueHex
}));
}
if("authorityCertIssuer" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: Array.from(this.authorityCertIssuer, element => element.toSchema())
}));
}
if("authorityCertSerialNumber" in this)
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
valueHex: this.authorityCertSerialNumber.valueBlock.valueHex
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if("keyIdentifier" in this)
object.keyIdentifier = this.keyIdentifier.toJSON();
if("authorityCertIssuer" in this)
object.authorityCertIssuer = Array.from(this.authorityCertIssuer, element => element.toJSON());
if("authorityCertSerialNumber" in this)
object.authorityCertSerialNumber = this.authorityCertSerialNumber.toJSON();
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,186 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class BasicConstraints
{
//**********************************************************************************
/**
* Constructor for BasicConstraints class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
* @property {Object} [cA]
* @property {Object} [pathLenConstraint]
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {boolean}
* @desc cA
*/
this.cA = getParametersValue(parameters, "cA", false);
if("pathLenConstraint" in parameters)
/**
* @type {number|Integer}
* @desc pathLenConstraint
*/
this.pathLenConstraint = getParametersValue(parameters, "pathLenConstraint", 0);
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "cA":
return false;
default:
throw new Error(`Invalid member name for BasicConstraints class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* BasicConstraints ::= SEQUENCE {
* cA BOOLEAN DEFAULT FALSE,
* pathLenConstraint INTEGER (0..MAX) OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [cA]
* @property {string} [pathLenConstraint]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Boolean({
optional: true,
name: (names.cA || "")
}),
new asn1js.Integer({
optional: true,
name: (names.pathLenConstraint || "")
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"cA",
"pathLenConstraint"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
BasicConstraints.schema({
names: {
cA: "cA",
pathLenConstraint: "pathLenConstraint"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for BasicConstraints");
//endregion
//region Get internal properties from parsed schema
if("cA" in asn1.result)
this.cA = asn1.result.cA.valueBlock.value;
if("pathLenConstraint" in asn1.result)
{
if(asn1.result.pathLenConstraint.valueBlock.isHexOnly)
this.pathLenConstraint = asn1.result.pathLenConstraint;
else
this.pathLenConstraint = asn1.result.pathLenConstraint.valueBlock.valueDec;
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if(this.cA !== BasicConstraints.defaultValues("cA"))
outputArray.push(new asn1js.Boolean({ value: this.cA }));
if("pathLenConstraint" in this)
{
if(this.pathLenConstraint instanceof asn1js.Integer)
outputArray.push(this.pathLenConstraint);
else
outputArray.push(new asn1js.Integer({ value: this.pathLenConstraint }));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if(this.cA !== BasicConstraints.defaultValues("cA"))
object.cA = this.cA;
if("pathLenConstraint" in this)
{
if(this.pathLenConstraint instanceof asn1js.Integer)
object.pathLenConstraint = this.pathLenConstraint.toJSON();
else
object.pathLenConstraint = this.pathLenConstraint;
}
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,562 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, isEqualBuffer, clearProps } from "./pvutils.js";
import { getAlgorithmByOID, getCrypto, getEngine } from "./common.js";
import ResponseData from "./ResponseData.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import Certificate from "./Certificate.js";
import CertID from "./CertID.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
import CertificateChainValidationEngine from "./CertificateChainValidationEngine.js";
//**************************************************************************************
/**
* Class from RFC6960
*/
export default class BasicOCSPResponse
{
//**********************************************************************************
/**
* Constructor for BasicOCSPResponse class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {ResponseData}
* @desc tbsResponseData
*/
this.tbsResponseData = getParametersValue(parameters, "tbsResponseData", BasicOCSPResponse.defaultValues("tbsResponseData"));
/**
* @type {AlgorithmIdentifier}
* @desc signatureAlgorithm
*/
this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", BasicOCSPResponse.defaultValues("signatureAlgorithm"));
/**
* @type {BitString}
* @desc signature
*/
this.signature = getParametersValue(parameters, "signature", BasicOCSPResponse.defaultValues("signature"));
if("certs" in parameters)
/**
* @type {Array.<Certificate>}
* @desc certs
*/
this.certs = getParametersValue(parameters, "certs", BasicOCSPResponse.defaultValues("certs"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "tbsResponseData":
return new ResponseData();
case "signatureAlgorithm":
return new AlgorithmIdentifier();
case "signature":
return new asn1js.BitString();
case "certs":
return [];
default:
throw new Error(`Invalid member name for BasicOCSPResponse class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "type":
{
// noinspection OverlyComplexBooleanExpressionJS
let comparisonResult = ((ResponseData.compareWithDefault("tbs", memberValue.tbs)) &&
(ResponseData.compareWithDefault("responderID", memberValue.responderID)) &&
(ResponseData.compareWithDefault("producedAt", memberValue.producedAt)) &&
(ResponseData.compareWithDefault("responses", memberValue.responses)));
if("responseExtensions" in memberValue)
comparisonResult = comparisonResult && (ResponseData.compareWithDefault("responseExtensions", memberValue.responseExtensions));
return comparisonResult;
}
case "signatureAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "signature":
return (memberValue.isEqual(BasicOCSPResponse.defaultValues(memberName)));
case "certs":
return (memberValue.length === 0);
default:
throw new Error(`Invalid member name for BasicOCSPResponse class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* BasicOCSPResponse ::= SEQUENCE {
* tbsResponseData ResponseData,
* signatureAlgorithm AlgorithmIdentifier,
* signature BIT STRING,
* certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [tbsResponseData]
* @property {string} [signatureAlgorithm]
* @property {string} [signature]
* @property {string} [certs]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || "BasicOCSPResponse"),
value: [
ResponseData.schema(names.tbsResponseData || {
names: {
blockName: "BasicOCSPResponse.tbsResponseData"
}
}),
AlgorithmIdentifier.schema(names.signatureAlgorithm || {
names: {
blockName: "BasicOCSPResponse.signatureAlgorithm"
}
}),
new asn1js.BitString({ name: (names.signature || "BasicOCSPResponse.signature") }),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Sequence({
value: [new asn1js.Repeated({
name: "BasicOCSPResponse.certs",
value: Certificate.schema(names.certs || {})
})]
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"BasicOCSPResponse.tbsResponseData",
"BasicOCSPResponse.signatureAlgorithm",
"BasicOCSPResponse.signature",
"BasicOCSPResponse.certs"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
BasicOCSPResponse.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for BasicOCSPResponse");
//endregion
//region Get internal properties from parsed schema
this.tbsResponseData = new ResponseData({ schema: asn1.result["BasicOCSPResponse.tbsResponseData"] });
this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result["BasicOCSPResponse.signatureAlgorithm"] });
this.signature = asn1.result["BasicOCSPResponse.signature"];
if("BasicOCSPResponse.certs" in asn1.result)
this.certs = Array.from(asn1.result["BasicOCSPResponse.certs"], element => new Certificate({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(this.tbsResponseData.toSchema());
outputArray.push(this.signatureAlgorithm.toSchema());
outputArray.push(this.signature);
//region Create array of certificates
if("certs" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Sequence({
value: Array.from(this.certs, element => element.toSchema())
})
]
}));
}
//endregion
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
tbsResponseData: this.tbsResponseData.toJSON(),
signatureAlgorithm: this.signatureAlgorithm.toJSON(),
signature: this.signature.toJSON()
};
if("certs" in this)
_object.certs = Array.from(this.certs, element => element.toJSON());
return _object;
}
//**********************************************************************************
/**
* Get OCSP response status for specific certificate
* @param {Certificate} certificate Certificate to be checked
* @param {Certificate} issuerCertificate Certificate of issuer for certificate to be checked
* @returns {Promise}
*/
getCertificateStatus(certificate, issuerCertificate)
{
//region Initial variables
let sequence = Promise.resolve();
const result = {
isForCertificate: false,
status: 2 // 0 = good, 1 = revoked, 2 = unknown
};
const hashesObject = {};
const certIDs = [];
const certIDPromises = [];
//endregion
//region Create all "certIDs" for input certificates
for(const response of this.tbsResponseData.responses)
{
const hashAlgorithm = getAlgorithmByOID(response.certID.hashAlgorithm.algorithmId);
if(("name" in hashAlgorithm) === false)
return Promise.reject(`Wrong CertID hashing algorithm: ${response.certID.hashAlgorithm.algorithmId}`);
if((hashAlgorithm.name in hashesObject) === false)
{
hashesObject[hashAlgorithm.name] = 1;
const certID = new CertID();
certIDs.push(certID);
certIDPromises.push(certID.createForCertificate(certificate, {
hashAlgorithm: hashAlgorithm.name,
issuerCertificate
}));
}
}
sequence = sequence.then(() =>
Promise.all(certIDPromises)
);
//endregion
//region Compare all response's "certIDs" with identifiers for input certificate
sequence = sequence.then(() =>
{
for(const response of this.tbsResponseData.responses)
{
for(const id of certIDs)
{
if(response.certID.isEqual(id))
{
result.isForCertificate = true;
try
{
switch(response.certStatus.idBlock.isConstructed)
{
case true:
if(response.certStatus.idBlock.tagNumber === 1)
result.status = 1; // revoked
break;
case false:
switch(response.certStatus.idBlock.tagNumber)
{
case 0: // good
result.status = 0;
break;
case 2: // unknown
result.status = 2;
break;
default:
}
break;
default:
}
}
catch(ex)
{
}
return result;
}
}
}
return result;
});
//endregion
return sequence;
}
//**********************************************************************************
/**
* Make signature for current OCSP Basic Response
* @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
* @param {string} [hashAlgorithm="SHA-1"] Hashing algorithm. Default SHA-1
* @returns {Promise}
*/
sign(privateKey, hashAlgorithm = "SHA-1")
{
//region Initial checking
//region Get a private key from function parameter
if(typeof privateKey === "undefined")
return Promise.reject("Need to provide a private key for signing");
//endregion
//endregion
//region Initial variables
let sequence = Promise.resolve();
let parameters;
const engine = getEngine();
//endregion
//region Get a "default parameters" for current algorithm and set correct signature algorithm
sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
sequence = sequence.then(result =>
{
parameters = result.parameters;
this.signatureAlgorithm = result.signatureAlgorithm;
});
//endregion
//region Create TBS data for signing
sequence = sequence.then(() =>
{
this.tbsResponseData.tbs = this.tbsResponseData.toSchema(true).toBER(false);
});
//endregion
//region Signing TBS data on provided private key
sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbsResponseData.tbs, privateKey, parameters));
sequence = sequence.then(result =>
{
this.signature = new asn1js.BitString({ valueHex: result });
});
//endregion
return sequence;
}
//**********************************************************************************
/**
* Verify existing OCSP Basic Response
* @param {Object} parameters Additional parameters
* @returns {Promise}
*/
verify(parameters = {})
{
//region Initial variables
let signerCert = null;
let certIndex = -1;
let sequence = Promise.resolve();
let trustedCerts = [];
const _this = this;
const engine = getEngine();
//endregion
//region Check amount of certificates
if(("certs" in this) === false)
return Promise.reject("No certificates attached to the BasicOCSPResponce");
//endregion
//region Get input values
if("trustedCerts" in parameters)
trustedCerts = parameters.trustedCerts;
//endregion
//region Aux functions
/**
* Check CA flag for the certificate
* @param {Certificate} cert Certificate to find CA flag for
* @returns {*}
*/
function checkCA(cert)
{
//region Do not include signer's certificate
if((cert.issuer.isEqual(signerCert.issuer) === true) && (cert.serialNumber.isEqual(signerCert.serialNumber) === true))
return null;
//endregion
let isCA = false;
for(const extension of cert.extensions)
{
if(extension.extnID === "2.5.29.19") // BasicConstraints
{
if("cA" in extension.parsedValue)
{
if(extension.parsedValue.cA === true)
isCA = true;
}
}
}
if(isCA)
return cert;
return null;
}
//endregion
//region Get a "crypto" extension
const crypto = getCrypto();
if(typeof crypto === "undefined")
return Promise.reject("Unable to create WebCrypto object");
//endregion
//region Find correct value for "responderID"
switch(true)
{
case (this.tbsResponseData.responderID instanceof RelativeDistinguishedNames): // [1] Name
sequence = sequence.then(() =>
{
for(const [index, certificate] of _this.certs.entries())
{
if(certificate.subject.isEqual(_this.tbsResponseData.responderID))
{
certIndex = index;
break;
}
}
});
break;
case (this.tbsResponseData.responderID instanceof asn1js.OctetString): // [2] KeyHash
sequence = sequence.then(() => Promise.all(Array.from(_this.certs, element =>
crypto.digest({ name: "sha-1" }, new Uint8Array(element.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex)))).then(results =>
{
for(const [index, ] of _this.certs.entries())
{
if(isEqualBuffer(results[index], _this.tbsResponseData.responderID.valueBlock.valueHex))
{
certIndex = index;
break;
}
}
}));
break;
default:
return Promise.reject("Wrong value for responderID");
}
//endregion
//region Make additional verification for signer's certificate
sequence = sequence.then(() =>
{
if(certIndex === (-1))
return Promise.reject("Correct certificate was not found in OCSP response");
signerCert = this.certs[certIndex];
return Promise.all(Array.from(_this.certs, element => checkCA(element))).then(promiseResults =>
{
const additionalCerts = [];
additionalCerts.push(signerCert);
for(const promiseResult of promiseResults)
{
if(promiseResult !== null)
additionalCerts.push(promiseResult);
}
const certChain = new CertificateChainValidationEngine({
certs: additionalCerts,
trustedCerts
});
return certChain.verify().then(verificationResult =>
{
if(verificationResult.result === true)
return Promise.resolve();
return Promise.reject("Validation of signer's certificate failed");
}, error =>
Promise.reject(`Validation of signer's certificate failed with error: ${((error instanceof Object) ? error.resultMessage : error)}`)
);
}, promiseError =>
Promise.reject(`Error during checking certificates for CA flag: ${promiseError}`)
);
});
//endregion
sequence = sequence.then(() => engine.subtle.verifyWithPublicKey(this.tbsResponseData.tbs, this.signature, this.certs[certIndex].subjectPublicKeyInfo, this.signatureAlgorithm));
return sequence;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,181 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, utilConcatBuf } from "./pvutils.js";
//**************************************************************************************
/**
* Class from https://docs.microsoft.com/en-us/windows/desktop/seccrypto/certification-authority-renewal
*/
export default class CAVersion
{
//**********************************************************************************
/**
* Constructor for CAVersion class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc certificateIndex
*/
this.certificateIndex = getParametersValue(parameters, "certificateIndex", CAVersion.defaultValues("certificateIndex"));
/**
* @type {number}
* @desc keyIndex
*/
this.keyIndex = getParametersValue(parameters, "keyIndex", CAVersion.defaultValues("keyIndex"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "certificateIndex":
case "keyIndex":
return 0;
default:
throw new Error(`Invalid member name for CAVersion class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CAVersion ::= INTEGER
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
return (new asn1js.Integer());
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Check the schema is valid
if(schema.constructor.blockName() !== asn1js.Integer.blockName())
throw new Error("Object's schema was not verified against input data for CAVersion");
//endregion
//region Check length of the input value and correct it if needed
let value = schema.valueBlock.valueHex.slice(0);
const valueView = new Uint8Array(value);
switch(true)
{
case (value.byteLength < 4):
{
const tempValue = new ArrayBuffer(4);
const tempValueView = new Uint8Array(tempValue);
tempValueView.set(valueView, 4 - value.byteLength);
value = tempValue.slice(0);
}
break;
case (value.byteLength > 4):
{
const tempValue = new ArrayBuffer(4);
const tempValueView = new Uint8Array(tempValue);
tempValueView.set(valueView.slice(0, 4));
value = tempValue.slice(0);
}
break;
default:
}
//endregion
//region Get internal properties from parsed schema
const keyIndexBuffer = value.slice(0, 2);
const keyIndexView8 = new Uint8Array(keyIndexBuffer);
let temp = keyIndexView8[0];
keyIndexView8[0] = keyIndexView8[1];
keyIndexView8[1] = temp;
const keyIndexView16 = new Uint16Array(keyIndexBuffer);
this.keyIndex = keyIndexView16[0];
const certificateIndexBuffer = value.slice(2);
const certificateIndexView8 = new Uint8Array(certificateIndexBuffer);
temp = certificateIndexView8[0];
certificateIndexView8[0] = certificateIndexView8[1];
certificateIndexView8[1] = temp;
const certificateIndexView16 = new Uint16Array(certificateIndexBuffer);
this.certificateIndex = certificateIndexView16[0];
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create raw values
const certificateIndexBuffer = new ArrayBuffer(2);
const certificateIndexView = new Uint16Array(certificateIndexBuffer);
certificateIndexView[0] = this.certificateIndex;
const certificateIndexView8 = new Uint8Array(certificateIndexBuffer);
let temp = certificateIndexView8[0];
certificateIndexView8[0] = certificateIndexView8[1];
certificateIndexView8[1] = temp;
const keyIndexBuffer = new ArrayBuffer(2);
const keyIndexView = new Uint16Array(keyIndexBuffer);
keyIndexView[0] = this.keyIndex;
const keyIndexView8 = new Uint8Array(keyIndexBuffer);
temp = keyIndexView8[0];
keyIndexView8[0] = keyIndexView8[1];
keyIndexView8[1] = temp;
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Integer({
valueHex: utilConcatBuf(keyIndexBuffer, certificateIndexBuffer)
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
certificateIndex: this.certificateIndex,
keyIndex: this.keyIndex
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,209 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import CertificateRevocationList from "./CertificateRevocationList.js";
//**************************************************************************************
/**
* Class from RFC7292
*/
export default class CRLBag
{
//**********************************************************************************
/**
* Constructor for CRLBag class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc crlId
*/
this.crlId = getParametersValue(parameters, "crlId", CRLBag.defaultValues("crlId"));
/**
* @type {*}
* @desc crlValue
*/
this.crlValue = getParametersValue(parameters, "crlValue", CRLBag.defaultValues("crlValue"));
if("parsedValue" in parameters)
/**
* @type {*}
* @desc parsedValue
*/
this.parsedValue = getParametersValue(parameters, "parsedValue", CRLBag.defaultValues("parsedValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "crlId":
return "";
case "crlValue":
return (new asn1js.Any());
case "parsedValue":
return {};
default:
throw new Error(`Invalid member name for CRLBag class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "crlId":
return (memberValue === "");
case "crlValue":
return (memberValue instanceof asn1js.Any);
case "parsedValue":
return ((memberValue instanceof Object) && (Object.keys(memberValue).length === 0));
default:
throw new Error(`Invalid member name for CRLBag class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CRLBag ::= SEQUENCE {
* crlId BAG-TYPE.&id ({CRLTypes}),
* crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId})
*}
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [id]
* @property {string} [value]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.id || "id") }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [new asn1js.Any({ name: (names.value || "value") })] // EXPLICIT ANY value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"crlId",
"crlValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CRLBag.schema({
names: {
id: "crlId",
value: "crlValue"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CRLBag");
//endregion
//region Get internal properties from parsed schema
this.crlId = asn1.result.crlId.valueBlock.toString();
this.crlValue = asn1.result.crlValue;
switch(this.crlId)
{
case "1.2.840.113549.1.9.23.1": // x509CRL
{
const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
this.parsedValue = new CertificateRevocationList({ schema: asn1Inner.result });
}
break;
default:
throw new Error(`Incorrect "crlId" value in CRLBag: ${this.crlId}`);
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
if("parsedValue" in this)
{
this.certId = "1.2.840.113549.1.9.23.1";
this.certValue = new asn1js.OctetString({ valueHex: this.parsedValue.toSchema().toBER(false) });
}
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.crlId }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.crlValue.toSchema()]
})
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
crlId: this.crlId,
crlValue: this.crlValue.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,134 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import DistributionPoint from "./DistributionPoint.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class CRLDistributionPoints
{
//**********************************************************************************
/**
* Constructor for CRLDistributionPoints class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<DistributionPoint>}
* @desc distributionPoints
*/
this.distributionPoints = getParametersValue(parameters, "distributionPoints", CRLDistributionPoints.defaultValues("distributionPoints"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "distributionPoints":
return [];
default:
throw new Error(`Invalid member name for CRLDistributionPoints class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [distributionPoints]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.distributionPoints || ""),
value: DistributionPoint.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"distributionPoints"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CRLDistributionPoints.schema({
names: {
distributionPoints: "distributionPoints"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CRLDistributionPoints");
//endregion
//region Get internal properties from parsed schema
this.distributionPoints = Array.from(asn1.result.distributionPoints, element => new DistributionPoint({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.distributionPoints, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
distributionPoints: Array.from(this.distributionPoints, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,229 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import Certificate from "./Certificate.js";
import AttributeCertificateV2 from "./AttributeCertificateV2.js";
//**************************************************************************************
/**
* Class from RFC7292
*/
export default class CertBag
{
//**********************************************************************************
/**
* Constructor for CertBag class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc certId
*/
this.certId = getParametersValue(parameters, "certId", CertBag.defaultValues("certId"));
/**
* @type {*}
* @desc certValue
*/
this.certValue = getParametersValue(parameters, "certValue", CertBag.defaultValues("certValue"));
if("parsedValue" in parameters)
/**
* @type {*}
* @desc parsedValue
*/
this.parsedValue = getParametersValue(parameters, "parsedValue", CertBag.defaultValues("parsedValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "certId":
return "";
case "certValue":
return (new asn1js.Any());
case "parsedValue":
return {};
default:
throw new Error(`Invalid member name for CertBag class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "certId":
return (memberValue === "");
case "certValue":
return (memberValue instanceof asn1js.Any);
case "parsedValue":
return ((memberValue instanceof Object) && (Object.keys(memberValue).length === 0));
default:
throw new Error(`Invalid member name for CertBag class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertBag ::= SEQUENCE {
* certId BAG-TYPE.&id ({CertTypes}),
* certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId})
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [id]
* @property {string} [value]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.id || "id") }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [new asn1js.Any({ name: (names.value || "value") })] // EXPLICIT ANY value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"certId",
"certValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertBag.schema({
names: {
id: "certId",
value: "certValue"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertBag");
//endregion
//region Get internal properties from parsed schema
this.certId = asn1.result.certId.valueBlock.toString();
this.certValue = asn1.result.certValue;
switch(this.certId)
{
case "1.2.840.113549.1.9.22.1": // x509Certificate
{
const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
try
{
this.parsedValue = new Certificate({ schema: asn1Inner.result });
}
catch(ex) // In some realizations the same OID used for attribute certificates
{
this.parsedValue = new AttributeCertificateV2({ schema: asn1Inner.result });
}
}
break;
case "1.2.840.113549.1.9.22.3": // attributeCertificate - (!!!) THIS OID IS SUBJECT FOR CHANGE IN FUTURE (!!!)
{
const asn1Inner = asn1js.fromBER(this.certValue.valueBlock.valueHex);
this.parsedValue = new AttributeCertificateV2({ schema: asn1Inner.result });
}
break;
case "1.2.840.113549.1.9.22.2": // sdsiCertificate
default:
throw new Error(`Incorrect "certId" value in CertBag: ${this.certId}`);
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
if("parsedValue" in this)
{
if("acinfo" in this.parsedValue) // attributeCertificate
this.certId = "1.2.840.113549.1.9.22.3";
else // x509Certificate
this.certId = "1.2.840.113549.1.9.22.1";
this.certValue = new asn1js.OctetString({ valueHex: this.parsedValue.toSchema().toBER(false) });
}
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.certId }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [(("toSchema" in this.certValue) ? this.certValue.toSchema() : this.certValue)]
})
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
certId: this.certId,
certValue: this.certValue.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,306 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, isEqualBuffer, clearProps } from "./pvutils.js";
import { getCrypto, getOIDByAlgorithm } from "./common.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC6960
*/
export default class CertID
{
//**********************************************************************************
/**
* Constructor for CertID class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AlgorithmIdentifier}
* @desc hashAlgorithm
*/
this.hashAlgorithm = getParametersValue(parameters, "hashAlgorithm", CertID.defaultValues("hashAlgorithm"));
/**
* @type {OctetString}
* @desc issuerNameHash
*/
this.issuerNameHash = getParametersValue(parameters, "issuerNameHash", CertID.defaultValues("issuerNameHash"));
/**
* @type {OctetString}
* @desc issuerKeyHash
*/
this.issuerKeyHash = getParametersValue(parameters, "issuerKeyHash", CertID.defaultValues("issuerKeyHash"));
/**
* @type {Integer}
* @desc serialNumber
*/
this.serialNumber = getParametersValue(parameters, "serialNumber", CertID.defaultValues("serialNumber"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "hashAlgorithm":
return new AlgorithmIdentifier();
case "issuerNameHash":
case "issuerKeyHash":
return new asn1js.OctetString();
case "serialNumber":
return new asn1js.Integer();
default:
throw new Error(`Invalid member name for CertID class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "hashAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "issuerNameHash":
case "issuerKeyHash":
case "serialNumber":
return (memberValue.isEqual(CertID.defaultValues(memberName)));
default:
throw new Error(`Invalid member name for CertID class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertID ::= SEQUENCE {
* hashAlgorithm AlgorithmIdentifier,
* issuerNameHash OCTET STRING, -- Hash of issuer's DN
* issuerKeyHash OCTET STRING, -- Hash of issuer's public key
* serialNumber CertificateSerialNumber }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [hashAlgorithm]
* @property {string} [hashAlgorithmObject]
* @property {string} [issuerNameHash]
* @property {string} [issuerKeyHash]
* @property {string} [serialNumber]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AlgorithmIdentifier.schema(names.hashAlgorithmObject || {
names: {
blockName: (names.hashAlgorithm || "")
}
}),
new asn1js.OctetString({ name: (names.issuerNameHash || "") }),
new asn1js.OctetString({ name: (names.issuerKeyHash || "") }),
new asn1js.Integer({ name: (names.serialNumber || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"hashAlgorithm",
"issuerNameHash",
"issuerKeyHash",
"serialNumber"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertID.schema({
names: {
hashAlgorithm: "hashAlgorithm",
issuerNameHash: "issuerNameHash",
issuerKeyHash: "issuerKeyHash",
serialNumber: "serialNumber"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertID");
//endregion
//region Get internal properties from parsed schema
this.hashAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.hashAlgorithm });
this.issuerNameHash = asn1.result.issuerNameHash;
this.issuerKeyHash = asn1.result.issuerKeyHash;
this.serialNumber = asn1.result.serialNumber;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
this.hashAlgorithm.toSchema(),
this.issuerNameHash,
this.issuerKeyHash,
this.serialNumber
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
hashAlgorithm: this.hashAlgorithm.toJSON(),
issuerNameHash: this.issuerNameHash.toJSON(),
issuerKeyHash: this.issuerKeyHash.toJSON(),
serialNumber: this.serialNumber.toJSON()
};
}
//**********************************************************************************
/**
* Check that two "CertIDs" are equal
* @param {CertID} certificateID Identifier of the certificate to be checked
* @returns {boolean}
*/
isEqual(certificateID)
{
//region Check "hashAlgorithm"
if(!this.hashAlgorithm.algorithmId === certificateID.hashAlgorithm.algorithmId)
return false;
//endregion
//region Check "issuerNameHash"
if(isEqualBuffer(this.issuerNameHash.valueBlock.valueHex, certificateID.issuerNameHash.valueBlock.valueHex) === false)
return false;
//endregion
//region Check "issuerKeyHash"
if(isEqualBuffer(this.issuerKeyHash.valueBlock.valueHex, certificateID.issuerKeyHash.valueBlock.valueHex) === false)
return false;
//endregion
//region Check "serialNumber"
if(!this.serialNumber.isEqual(certificateID.serialNumber))
return false;
//endregion
return true;
}
//**********************************************************************************
/**
* Making OCSP certificate identifier for specific certificate
* @param {Certificate} certificate Certificate making OCSP Request for
* @param {Object} parameters Additional parameters
* @returns {Promise}
*/
createForCertificate(certificate, parameters)
{
//region Initial variables
let sequence = Promise.resolve();
let issuerCertificate;
//endregion
//region Get a "crypto" extension
const crypto = getCrypto();
if(typeof crypto === "undefined")
return Promise.reject("Unable to create WebCrypto object");
//endregion
//region Check input parameters
if(("hashAlgorithm" in parameters) === false)
return Promise.reject("Parameter \"hashAlgorithm\" is mandatory for \"OCSP_REQUEST.createForCertificate\"");
const hashOID = getOIDByAlgorithm({ name: parameters.hashAlgorithm });
if(hashOID === "")
return Promise.reject(`Incorrect "hashAlgorithm": ${this.hashAlgorithm}`);
this.hashAlgorithm = new AlgorithmIdentifier({
algorithmId: hashOID,
algorithmParams: new asn1js.Null()
});
if("issuerCertificate" in parameters)
issuerCertificate = parameters.issuerCertificate;
else
return Promise.reject("Parameter \"issuerCertificate\" is mandatory for \"OCSP_REQUEST.createForCertificate\"");
//endregion
//region Initialize "serialNumber" field
this.serialNumber = certificate.serialNumber;
//endregion
//region Create "issuerNameHash"
sequence = sequence.then(() =>
crypto.digest({ name: parameters.hashAlgorithm }, issuerCertificate.subject.toSchema().toBER(false)),
error =>
Promise.reject(error)
);
//endregion
//region Create "issuerKeyHash"
sequence = sequence.then(result =>
{
this.issuerNameHash = new asn1js.OctetString({ valueHex: result });
const issuerKeyBuffer = issuerCertificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex;
return crypto.digest({ name: parameters.hashAlgorithm }, issuerKeyBuffer);
}, error =>
Promise.reject(error)
).then(result =>
{
this.issuerKeyHash = new asn1js.OctetString({ valueHex: result });
}, error =>
Promise.reject(error)
);
//endregion
return sequence;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,625 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, bufferToHexCodes, clearProps } from "./pvutils.js";
import { getCrypto, getEngine } from "./common.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
import Time from "./Time.js";
import PublicKeyInfo from "./PublicKeyInfo.js";
import Extension from "./Extension.js";
import Extensions from "./Extensions.js";
//**************************************************************************************
function tbsCertificate(parameters = {})
{
//TBSCertificate ::= SEQUENCE {
// version [0] EXPLICIT Version DEFAULT v1,
// serialNumber CertificateSerialNumber,
// signature AlgorithmIdentifier,
// issuer Name,
// validity Validity,
// subject Name,
// subjectPublicKeyInfo SubjectPublicKeyInfo,
// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version MUST be v2 or v3
// extensions [3] EXPLICIT Extensions OPTIONAL
// -- If present, version MUST be v3
//}
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [tbsCertificateVersion]
* @property {string} [tbsCertificateSerialNumber]
* @property {string} [signature]
* @property {string} [issuer]
* @property {string} [tbsCertificateValidity]
* @property {string} [notBefore]
* @property {string} [notAfter]
* @property {string} [subject]
* @property {string} [subjectPublicKeyInfo]
* @property {string} [tbsCertificateIssuerUniqueID]
* @property {string} [tbsCertificateSubjectUniqueID]
* @property {string} [extensions]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || "tbsCertificate"),
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Integer({ name: (names.tbsCertificateVersion || "tbsCertificate.version") }) // EXPLICIT integer value
]
}),
new asn1js.Integer({ name: (names.tbsCertificateSerialNumber || "tbsCertificate.serialNumber") }),
AlgorithmIdentifier.schema(names.signature || {
names: {
blockName: "tbsCertificate.signature"
}
}),
RelativeDistinguishedNames.schema(names.issuer || {
names: {
blockName: "tbsCertificate.issuer"
}
}),
new asn1js.Sequence({
name: (names.tbsCertificateValidity || "tbsCertificate.validity"),
value: [
Time.schema(names.notBefore || {
names: {
utcTimeName: "tbsCertificate.notBefore",
generalTimeName: "tbsCertificate.notBefore"
}
}),
Time.schema(names.notAfter || {
names: {
utcTimeName: "tbsCertificate.notAfter",
generalTimeName: "tbsCertificate.notAfter"
}
})
]
}),
RelativeDistinguishedNames.schema(names.subject || {
names: {
blockName: "tbsCertificate.subject"
}
}),
PublicKeyInfo.schema(names.subjectPublicKeyInfo || {
names: {
blockName: "tbsCertificate.subjectPublicKeyInfo"
}
}),
new asn1js.Primitive({
name: (names.tbsCertificateIssuerUniqueID || "tbsCertificate.issuerUniqueID"),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
}
}), // IMPLICIT bistring value
new asn1js.Primitive({
name: (names.tbsCertificateSubjectUniqueID || "tbsCertificate.subjectUniqueID"),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
}
}), // IMPLICIT bistring value
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
value: [Extensions.schema(names.extensions || {
names: {
blockName: "tbsCertificate.extensions"
}
})]
}) // EXPLICIT SEQUENCE value
]
}));
}
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class Certificate
{
//**********************************************************************************
/**
* Constructor for Certificate class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {ArrayBuffer}
* @desc ToBeSigned (TBS) part of the certificate
*/
this.tbs = getParametersValue(parameters, "tbs", Certificate.defaultValues("tbs"));
/**
* @type {number}
* @desc Version number
*/
this.version = getParametersValue(parameters, "version", Certificate.defaultValues("version"));
/**
* @type {Integer}
* @desc Serial number of the certificate
*/
this.serialNumber = getParametersValue(parameters, "serialNumber", Certificate.defaultValues("serialNumber"));
/**
* @type {AlgorithmIdentifier}
* @desc This field contains the algorithm identifier for the algorithm used by the CA to sign the certificate
*/
this.signature = getParametersValue(parameters, "signature", Certificate.defaultValues("signature"));
/**
* @type {RelativeDistinguishedNames}
* @desc The issuer field identifies the entity that has signed and issued the certificate
*/
this.issuer = getParametersValue(parameters, "issuer", Certificate.defaultValues("issuer"));
/**
* @type {Time}
* @desc The date on which the certificate validity period begins
*/
this.notBefore = getParametersValue(parameters, "notBefore", Certificate.defaultValues("notBefore"));
/**
* @type {Time}
* @desc The date on which the certificate validity period ends
*/
this.notAfter = getParametersValue(parameters, "notAfter", Certificate.defaultValues("notAfter"));
/**
* @type {RelativeDistinguishedNames}
* @desc The subject field identifies the entity associated with the public key stored in the subject public key field
*/
this.subject = getParametersValue(parameters, "subject", Certificate.defaultValues("subject"));
/**
* @type {PublicKeyInfo}
* @desc This field is used to carry the public key and identify the algorithm with which the key is used
*/
this.subjectPublicKeyInfo = getParametersValue(parameters, "subjectPublicKeyInfo", Certificate.defaultValues("subjectPublicKeyInfo"));
if("issuerUniqueID" in parameters)
/**
* @type {ArrayBuffer}
* @desc The subject and issuer unique identifiers are present in the certificate to handle the possibility of reuse of subject and/or issuer names over time
*/
this.issuerUniqueID = getParametersValue(parameters, "issuerUniqueID", Certificate.defaultValues("issuerUniqueID"));
if("subjectUniqueID" in parameters)
/**
* @type {ArrayBuffer}
* @desc The subject and issuer unique identifiers are present in the certificate to handle the possibility of reuse of subject and/or issuer names over time
*/
this.subjectUniqueID = getParametersValue(parameters, "subjectUniqueID", Certificate.defaultValues("subjectUniqueID"));
if("extensions" in parameters)
/**
* @type {Array}
* @desc If present, this field is a SEQUENCE of one or more certificate extensions
*/
this.extensions = getParametersValue(parameters, "extensions", Certificate.defaultValues("extensions"));
/**
* @type {AlgorithmIdentifier}
* @desc The signatureAlgorithm field contains the identifier for the cryptographic algorithm used by the CA to sign this certificate
*/
this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", Certificate.defaultValues("signatureAlgorithm"));
/**
* @type {BitString}
* @desc The signatureValue field contains a digital signature computed upon the ASN.1 DER encoded tbsCertificate
*/
this.signatureValue = getParametersValue(parameters, "signatureValue", Certificate.defaultValues("signatureValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "tbs":
return new ArrayBuffer(0);
case "version":
return 0;
case "serialNumber":
return new asn1js.Integer();
case "signature":
return new AlgorithmIdentifier();
case "issuer":
return new RelativeDistinguishedNames();
case "notBefore":
return new Time();
case "notAfter":
return new Time();
case "subject":
return new RelativeDistinguishedNames();
case "subjectPublicKeyInfo":
return new PublicKeyInfo();
case "issuerUniqueID":
return new ArrayBuffer(0);
case "subjectUniqueID":
return new ArrayBuffer(0);
case "extensions":
return [];
case "signatureAlgorithm":
return new AlgorithmIdentifier();
case "signatureValue":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for Certificate class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* Certificate ::= SEQUENCE {
* tbsCertificate TBSCertificate,
* signatureAlgorithm AlgorithmIdentifier,
* signatureValue BIT STRING }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [tbsCertificate]
* @property {string} [signatureAlgorithm]
* @property {string} [signatureValue]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
tbsCertificate(names.tbsCertificate),
AlgorithmIdentifier.schema(names.signatureAlgorithm || {
names: {
blockName: "signatureAlgorithm"
}
}),
new asn1js.BitString({ name: (names.signatureValue || "signatureValue") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"tbsCertificate",
"tbsCertificate.extensions",
"tbsCertificate.version",
"tbsCertificate.serialNumber",
"tbsCertificate.signature",
"tbsCertificate.issuer",
"tbsCertificate.notBefore",
"tbsCertificate.notAfter",
"tbsCertificate.subject",
"tbsCertificate.subjectPublicKeyInfo",
"tbsCertificate.issuerUniqueID",
"tbsCertificate.subjectUniqueID",
"signatureAlgorithm",
"signatureValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
Certificate.schema({
names: {
tbsCertificate: {
names: {
extensions: {
names: {
extensions: "tbsCertificate.extensions"
}
}
}
}
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for Certificate");
//endregion
//region Get internal properties from parsed schema
this.tbs = asn1.result.tbsCertificate.valueBeforeDecode;
if("tbsCertificate.version" in asn1.result)
this.version = asn1.result["tbsCertificate.version"].valueBlock.valueDec;
this.serialNumber = asn1.result["tbsCertificate.serialNumber"];
this.signature = new AlgorithmIdentifier({ schema: asn1.result["tbsCertificate.signature"] });
this.issuer = new RelativeDistinguishedNames({ schema: asn1.result["tbsCertificate.issuer"] });
this.notBefore = new Time({ schema: asn1.result["tbsCertificate.notBefore"] });
this.notAfter = new Time({ schema: asn1.result["tbsCertificate.notAfter"] });
this.subject = new RelativeDistinguishedNames({ schema: asn1.result["tbsCertificate.subject"] });
this.subjectPublicKeyInfo = new PublicKeyInfo({ schema: asn1.result["tbsCertificate.subjectPublicKeyInfo"] });
if("tbsCertificate.issuerUniqueID" in asn1.result)
this.issuerUniqueID = asn1.result["tbsCertificate.issuerUniqueID"].valueBlock.valueHex;
if("tbsCertificate.subjectUniqueID" in asn1.result)
this.subjectUniqueID = asn1.result["tbsCertificate.subjectUniqueID"].valueBlock.valueHex;
if("tbsCertificate.extensions" in asn1.result)
this.extensions = Array.from(asn1.result["tbsCertificate.extensions"], element => new Extension({ schema: element }));
this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
this.signatureValue = asn1.result.signatureValue;
//endregion
}
//**********************************************************************************
/**
* Create ASN.1 schema for existing values of TBS part for the certificate
*/
encodeTBS()
{
//region Create array for output sequence
const outputArray = [];
if(("version" in this) && (this.version !== Certificate.defaultValues("version")))
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Integer({ value: this.version }) // EXPLICIT integer value
]
}));
}
outputArray.push(this.serialNumber);
outputArray.push(this.signature.toSchema());
outputArray.push(this.issuer.toSchema());
outputArray.push(new asn1js.Sequence({
value: [
this.notBefore.toSchema(),
this.notAfter.toSchema()
]
}));
outputArray.push(this.subject.toSchema());
outputArray.push(this.subjectPublicKeyInfo.toSchema());
if("issuerUniqueID" in this)
{
outputArray.push(new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
valueHex: this.issuerUniqueID
}));
}
if("subjectUniqueID" in this)
{
outputArray.push(new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
valueHex: this.subjectUniqueID
}));
}
if("extensions" in this)
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
value: [new asn1js.Sequence({
value: Array.from(this.extensions, element => element.toSchema())
})]
}));
}
//endregion
//region Create and return output sequence
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema(encodeFlag = false)
{
let tbsSchema = {};
//region Decode stored TBS value
if(encodeFlag === false)
{
if(this.tbs.length === 0) // No stored certificate TBS part
return Certificate.schema().value[0];
tbsSchema = asn1js.fromBER(this.tbs).result;
}
//endregion
//region Create TBS schema via assembling from TBS parts
else
tbsSchema = this.encodeTBS();
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
tbsSchema,
this.signatureAlgorithm.toSchema(),
this.signatureValue
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
tbs: bufferToHexCodes(this.tbs, 0, this.tbs.byteLength),
serialNumber: this.serialNumber.toJSON(),
signature: this.signature.toJSON(),
issuer: this.issuer.toJSON(),
notBefore: this.notBefore.toJSON(),
notAfter: this.notAfter.toJSON(),
subject: this.subject.toJSON(),
subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(),
signatureAlgorithm: this.signatureAlgorithm.toJSON(),
signatureValue: this.signatureValue.toJSON()
};
if(("version" in this) && (this.version !== Certificate.defaultValues("version")))
object.version = this.version;
if("issuerUniqueID" in this)
object.issuerUniqueID = bufferToHexCodes(this.issuerUniqueID, 0, this.issuerUniqueID.byteLength);
if("subjectUniqueID" in this)
object.subjectUniqueID = bufferToHexCodes(this.subjectUniqueID, 0, this.subjectUniqueID.byteLength);
if("extensions" in this)
object.extensions = Array.from(this.extensions, element => element.toJSON());
return object;
}
//**********************************************************************************
/**
* Importing public key for current certificate
*/
getPublicKey(parameters = null)
{
return getEngine().subtle.getPublicKey(this.subjectPublicKeyInfo, this.signatureAlgorithm, parameters);
}
//**********************************************************************************
/**
* Get hash value for subject public key (default SHA-1)
* @param {String} [hashAlgorithm=SHA-1] Hashing algorithm name
*/
getKeyHash(hashAlgorithm = "SHA-1")
{
//region Get a "crypto" extension
const crypto = getCrypto();
if(typeof crypto === "undefined")
return Promise.reject("Unable to create WebCrypto object");
//endregion
return crypto.digest({ name: hashAlgorithm }, new Uint8Array(this.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex));
}
//**********************************************************************************
/**
* Make a signature for current value from TBS section
* @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
* @param {string} [hashAlgorithm="SHA-1"] Hashing algorithm
*/
sign(privateKey, hashAlgorithm = "SHA-1")
{
//region Initial checking
//region Check private key
if(typeof privateKey === "undefined")
return Promise.reject("Need to provide a private key for signing");
//endregion
//endregion
//region Initial variables
let sequence = Promise.resolve();
let parameters;
const engine = getEngine();
//endregion
//region Get a "default parameters" for current algorithm and set correct signature algorithm
sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
sequence = sequence.then(result =>
{
parameters = result.parameters;
this.signature = result.signatureAlgorithm;
this.signatureAlgorithm = result.signatureAlgorithm;
});
//endregion
//region Create TBS data for signing
sequence = sequence.then(() =>
{
this.tbs = this.encodeTBS().toBER(false);
});
//endregion
//region Signing TBS data on provided private key
sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
sequence = sequence.then(result =>
{
this.signatureValue = new asn1js.BitString({ valueHex: result });
});
//endregion
return sequence;
}
//**********************************************************************************
verify(issuerCertificate = null)
{
//region Global variables
let subjectPublicKeyInfo = {};
//endregion
//region Set correct "subjectPublicKeyInfo" value
if(issuerCertificate !== null)
subjectPublicKeyInfo = issuerCertificate.subjectPublicKeyInfo;
else
{
if(this.issuer.isEqual(this.subject)) // Self-signed certificate
subjectPublicKeyInfo = this.subjectPublicKeyInfo;
}
if((subjectPublicKeyInfo instanceof PublicKeyInfo) === false)
return Promise.reject("Please provide issuer certificate as a parameter");
//endregion
return getEngine().subtle.verifyWithPublicKey(this.tbs, this.signatureValue, subjectPublicKeyInfo, this.signatureAlgorithm);
}
//**********************************************************************************
}
//**************************************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -1,134 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import PolicyInformation from "./PolicyInformation.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class CertificatePolicies
{
//**********************************************************************************
/**
* Constructor for CertificatePolicies class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<PolicyInformation>}
* @desc certificatePolicies
*/
this.certificatePolicies = getParametersValue(parameters, "certificatePolicies", CertificatePolicies.defaultValues("certificatePolicies"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "certificatePolicies":
return [];
default:
throw new Error(`Invalid member name for CertificatePolicies class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [certificatePolicies]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.certificatePolicies || ""),
value: PolicyInformation.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"certificatePolicies"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertificatePolicies.schema({
names: {
certificatePolicies: "certificatePolicies"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertificatePolicies");
//endregion
//region Get internal properties from parsed schema
this.certificatePolicies = Array.from(asn1.result.certificatePolicies, element => new PolicyInformation({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.certificatePolicies, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
certificatePolicies: Array.from(this.certificatePolicies, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,538 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, bufferToHexCodes, clearProps } from "./pvutils.js";
import { getEngine } from "./common.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
import Time from "./Time.js";
import RevokedCertificate from "./RevokedCertificate.js";
import Extensions from "./Extensions.js";
//**************************************************************************************
function tbsCertList(parameters = {})
{
//TBSCertList ::= SEQUENCE {
// version Version OPTIONAL,
// -- if present, MUST be v2
// signature AlgorithmIdentifier,
// issuer Name,
// thisUpdate Time,
// nextUpdate Time OPTIONAL,
// revokedCertificates SEQUENCE OF SEQUENCE {
// userCertificate CertificateSerialNumber,
// revocationDate Time,
// crlEntryExtensions Extensions OPTIONAL
// -- if present, version MUST be v2
// } OPTIONAL,
// crlExtensions [0] EXPLICIT Extensions OPTIONAL
// -- if present, version MUST be v2
//}
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [tbsCertListVersion]
* @property {string} [signature]
* @property {string} [issuer]
* @property {string} [tbsCertListThisUpdate]
* @property {string} [tbsCertListNextUpdate]
* @property {string} [tbsCertListRevokedCertificates]
* @property {string} [crlExtensions]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || "tbsCertList"),
value: [
new asn1js.Integer({
optional: true,
name: (names.tbsCertListVersion || "tbsCertList.version"),
value: 2
}), // EXPLICIT integer value (v2)
AlgorithmIdentifier.schema(names.signature || {
names: {
blockName: "tbsCertList.signature"
}
}),
RelativeDistinguishedNames.schema(names.issuer || {
names: {
blockName: "tbsCertList.issuer"
}
}),
Time.schema(names.tbsCertListThisUpdate || {
names: {
utcTimeName: "tbsCertList.thisUpdate",
generalTimeName: "tbsCertList.thisUpdate"
}
}),
Time.schema(names.tbsCertListNextUpdate || {
names: {
utcTimeName: "tbsCertList.nextUpdate",
generalTimeName: "tbsCertList.nextUpdate"
}
}, true),
new asn1js.Sequence({
optional: true,
value: [
new asn1js.Repeated({
name: (names.tbsCertListRevokedCertificates || "tbsCertList.revokedCertificates"),
value: new asn1js.Sequence({
value: [
new asn1js.Integer(),
Time.schema(),
Extensions.schema({}, true)
]
})
})
]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [Extensions.schema(names.crlExtensions || {
names: {
blockName: "tbsCertList.extensions"
}
})]
}) // EXPLICIT SEQUENCE value
]
}));
}
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class CertificateRevocationList {
//**********************************************************************************
/**
* Constructor for Attribute class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {ArrayBuffer}
* @desc tbs
*/
this.tbs = getParametersValue(parameters, "tbs", CertificateRevocationList.defaultValues("tbs"));
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", CertificateRevocationList.defaultValues("version"));
/**
* @type {AlgorithmIdentifier}
* @desc signature
*/
this.signature = getParametersValue(parameters, "signature", CertificateRevocationList.defaultValues("signature"));
/**
* @type {RelativeDistinguishedNames}
* @desc issuer
*/
this.issuer = getParametersValue(parameters, "issuer", CertificateRevocationList.defaultValues("issuer"));
/**
* @type {Time}
* @desc thisUpdate
*/
this.thisUpdate = getParametersValue(parameters, "thisUpdate", CertificateRevocationList.defaultValues("thisUpdate"));
if("nextUpdate" in parameters)
/**
* @type {Time}
* @desc nextUpdate
*/
this.nextUpdate = getParametersValue(parameters, "nextUpdate", CertificateRevocationList.defaultValues("nextUpdate"));
if("revokedCertificates" in parameters)
/**
* @type {Array.<RevokedCertificate>}
* @desc revokedCertificates
*/
this.revokedCertificates = getParametersValue(parameters, "revokedCertificates", CertificateRevocationList.defaultValues("revokedCertificates"));
if("crlExtensions" in parameters)
/**
* @type {Extensions}
* @desc crlExtensions
*/
this.crlExtensions = getParametersValue(parameters, "crlExtensions", CertificateRevocationList.defaultValues("crlExtensions"));
/**
* @type {AlgorithmIdentifier}
* @desc signatureAlgorithm
*/
this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", CertificateRevocationList.defaultValues("signatureAlgorithm"));
/**
* @type {BitString}
* @desc signatureValue
*/
this.signatureValue = getParametersValue(parameters, "signatureValue", CertificateRevocationList.defaultValues("signatureValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "tbs":
return new ArrayBuffer(0);
case "version":
return 1;
case "signature":
return new AlgorithmIdentifier();
case "issuer":
return new RelativeDistinguishedNames();
case "thisUpdate":
return new Time();
case "nextUpdate":
return new Time();
case "revokedCertificates":
return [];
case "crlExtensions":
return new Extensions();
case "signatureAlgorithm":
return new AlgorithmIdentifier();
case "signatureValue":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for CertificateRevocationList class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertificateList ::= SEQUENCE {
* tbsCertList TBSCertList,
* signatureAlgorithm AlgorithmIdentifier,
* signatureValue BIT STRING }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [signatureAlgorithm]
* @property {string} [signatureValue]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || "CertificateList"),
value: [
tbsCertList(parameters),
AlgorithmIdentifier.schema(names.signatureAlgorithm || {
names: {
blockName: "signatureAlgorithm"
}
}),
new asn1js.BitString({ name: (names.signatureValue || "signatureValue") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"tbsCertList",
"tbsCertList.version",
"tbsCertList.signature",
"tbsCertList.issuer",
"tbsCertList.thisUpdate",
"tbsCertList.nextUpdate",
"tbsCertList.revokedCertificates",
"tbsCertList.extensions",
"signatureAlgorithm",
"signatureValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertificateRevocationList.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertificateRevocationList");
//endregion
//region Get internal properties from parsed schema
// noinspection JSUnresolvedVariable
this.tbs = asn1.result.tbsCertList.valueBeforeDecode;
if("tbsCertList.version" in asn1.result)
this.version = asn1.result["tbsCertList.version"].valueBlock.valueDec;
this.signature = new AlgorithmIdentifier({ schema: asn1.result["tbsCertList.signature"] });
this.issuer = new RelativeDistinguishedNames({ schema: asn1.result["tbsCertList.issuer"] });
this.thisUpdate = new Time({ schema: asn1.result["tbsCertList.thisUpdate"] });
if("tbsCertList.nextUpdate" in asn1.result)
this.nextUpdate = new Time({ schema: asn1.result["tbsCertList.nextUpdate"] });
if("tbsCertList.revokedCertificates" in asn1.result)
this.revokedCertificates = Array.from(asn1.result["tbsCertList.revokedCertificates"], element => new RevokedCertificate({ schema: element }));
if("tbsCertList.extensions" in asn1.result)
this.crlExtensions = new Extensions({ schema: asn1.result["tbsCertList.extensions"] });
this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
this.signatureValue = asn1.result.signatureValue;
//endregion
}
//**********************************************************************************
encodeTBS()
{
//region Create array for output sequence
const outputArray = [];
if(this.version !== CertificateRevocationList.defaultValues("version"))
outputArray.push(new asn1js.Integer({ value: this.version }));
outputArray.push(this.signature.toSchema());
outputArray.push(this.issuer.toSchema());
outputArray.push(this.thisUpdate.toSchema());
if("nextUpdate" in this)
outputArray.push(this.nextUpdate.toSchema());
if("revokedCertificates" in this)
{
outputArray.push(new asn1js.Sequence({
value: Array.from(this.revokedCertificates, element => element.toSchema())
}));
}
if("crlExtensions" in this)
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
this.crlExtensions.toSchema()
]
}));
}
//endregion
return (new asn1js.Sequence({
value: outputArray
}));
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema(encodeFlag = false)
{
//region Decode stored TBS value
let tbsSchema;
if(encodeFlag === false)
{
if(this.tbs.length === 0) // No stored TBS part
return CertificateRevocationList.schema();
tbsSchema = asn1js.fromBER(this.tbs).result;
}
//endregion
//region Create TBS schema via assembling from TBS parts
else
tbsSchema = this.encodeTBS();
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
tbsSchema,
this.signatureAlgorithm.toSchema(),
this.signatureValue
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
tbs: bufferToHexCodes(this.tbs, 0, this.tbs.byteLength),
signature: this.signature.toJSON(),
issuer: this.issuer.toJSON(),
thisUpdate: this.thisUpdate.toJSON(),
signatureAlgorithm: this.signatureAlgorithm.toJSON(),
signatureValue: this.signatureValue.toJSON()
};
if(this.version !== CertificateRevocationList.defaultValues("version"))
object.version = this.version;
if("nextUpdate" in this)
object.nextUpdate = this.nextUpdate.toJSON();
if("revokedCertificates" in this)
object.revokedCertificates = Array.from(this.revokedCertificates, element => element.toJSON());
if("crlExtensions" in this)
object.crlExtensions = this.crlExtensions.toJSON();
return object;
}
//**********************************************************************************
isCertificateRevoked(certificate)
{
//region Check that issuer of the input certificate is the same with issuer of this CRL
if(this.issuer.isEqual(certificate.issuer) === false)
return false;
//endregion
//region Check that there are revoked certificates in this CRL
if(("revokedCertificates" in this) === false)
return false;
//endregion
//region Search for input certificate in revoked certificates array
for(const revokedCertificate of this.revokedCertificates)
{
if(revokedCertificate.userCertificate.isEqual(certificate.serialNumber))
return true;
}
//endregion
return false;
}
//**********************************************************************************
/**
* Make a signature for existing CRL data
* @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
* @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
*/
sign(privateKey, hashAlgorithm = "SHA-1")
{
//region Initial checking
//region Get a private key from function parameter
if(typeof privateKey === "undefined")
return Promise.reject("Need to provide a private key for signing");
//endregion
//endregion
//region Initial variables
let sequence = Promise.resolve();
let parameters;
const engine = getEngine();
//endregion
//region Get a "default parameters" for current algorithm and set correct signature algorithm
sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
sequence = sequence.then(result =>
{
parameters = result.parameters;
this.signature = result.signatureAlgorithm;
this.signatureAlgorithm = result.signatureAlgorithm;
});
//endregion
//region Create TBS data for signing
sequence = sequence.then(() =>
{
this.tbs = this.encodeTBS().toBER(false);
});
//endregion
//region Signing TBS data on provided private key
sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
sequence = sequence.then(result =>
{
this.signatureValue = new asn1js.BitString({ valueHex: result });
});
//endregion
return sequence;
}
//**********************************************************************************
/**
* Verify existing signature
* @param {{[issuerCertificate]: Object, [publicKeyInfo]: Object}} parameters
* @returns {*}
*/
verify(parameters = {})
{
//region Global variables
let sequence = Promise.resolve();
let subjectPublicKeyInfo = -1;
const engine = getEngine();
//endregion
//region Get information about CRL issuer certificate
if("issuerCertificate" in parameters) // "issuerCertificate" must be of type "Certificate"
{
subjectPublicKeyInfo = parameters.issuerCertificate.subjectPublicKeyInfo;
// The CRL issuer name and "issuerCertificate" subject name are not equal
if(this.issuer.isEqual(parameters.issuerCertificate.subject) === false)
return Promise.resolve(false);
}
//region In case if there is only public key during verification
if("publicKeyInfo" in parameters)
subjectPublicKeyInfo = parameters.publicKeyInfo; // Must be of type "PublicKeyInfo"
//endregion
if(("subjectPublicKey" in subjectPublicKeyInfo) === false)
return Promise.reject("Issuer's certificate must be provided as an input parameter");
//endregion
//region Check the CRL for unknown critical extensions
if("crlExtensions" in this)
{
for(const extension of this.crlExtensions.extensions)
{
if(extension.critical)
{
// We can not be sure that unknown extension has no value for CRL signature
if(("parsedValue" in extension) === false)
return Promise.resolve(false);
}
}
}
//endregion
sequence = sequence.then(() => engine.subtle.verifyWithPublicKey(this.tbs, this.signatureValue, subjectPublicKeyInfo, this.signatureAlgorithm));
return sequence;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,235 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import Certificate from "./Certificate.js";
import AttributeCertificateV1 from "./AttributeCertificateV1.js";
import AttributeCertificateV2 from "./AttributeCertificateV2.js";
import OtherCertificateFormat from "./OtherCertificateFormat.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class CertificateSet
{
//**********************************************************************************
/**
* Constructor for CertificateSet class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array}
* @desc certificates
*/
this.certificates = getParametersValue(parameters, "certificates", CertificateSet.defaultValues("certificates"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "certificates":
return [];
default:
throw new Error(`Invalid member name for Attribute class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertificateSet ::= SET OF CertificateChoices
*
* CertificateChoices ::= CHOICE {
* certificate Certificate,
* extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete
* v1AttrCert [1] IMPLICIT AttributeCertificateV1, -- Obsolete
* v2AttrCert [2] IMPLICIT AttributeCertificateV2,
* other [3] IMPLICIT OtherCertificateFormat }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
*/
const names = getParametersValue(parameters, "names", {});
return (
new asn1js.Set({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.certificates || "certificates"),
value: new asn1js.Choice({
value: [
Certificate.schema(),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Any()
]
}), // JUST A STUB
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: AttributeCertificateV1.schema().valueBlock.value
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
value: AttributeCertificateV2.schema().valueBlock.value
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
value: OtherCertificateFormat.schema().valueBlock.value
})
]
})
})
]
})
);
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"certificates"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertificateSet.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertificateSet");
//endregion
//region Get internal properties from parsed schema
this.certificates = Array.from(asn1.result.certificates || [], element =>
{
const initialTagNumber = element.idBlock.tagNumber;
if(element.idBlock.tagClass === 1)
return new Certificate({ schema: element });
//region Making "Sequence" from "Constructed" value
const elementSequence = new asn1js.Sequence({
value: element.valueBlock.value
});
//endregion
switch(initialTagNumber)
{
case 1:
return new AttributeCertificateV1({ schema: elementSequence });
case 2:
return new AttributeCertificateV2({ schema: elementSequence });
case 3:
return new OtherCertificateFormat({ schema: elementSequence });
case 0:
default:
}
return element;
});
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Set({
value: Array.from(this.certificates, element =>
{
switch(true)
{
case (element instanceof Certificate):
return element.toSchema();
case (element instanceof AttributeCertificateV1):
return new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: 1 // [1]
},
value: element.toSchema().valueBlock.value
});
case (element instanceof AttributeCertificateV2):
return new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: 2 // [2]
},
value: element.toSchema().valueBlock.value
});
case (element instanceof OtherCertificateFormat):
return new asn1js.Constructed({
idBlock: {
tagClass: 3,
tagNumber: 3 // [3]
},
value: element.toSchema().valueBlock.value
});
default:
}
return element;
})
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
certificates: Array.from(this.certificates, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,191 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from "[MS-WCCE]: Windows Client Certificate Enrollment Protocol"
*/
export default class CertificateTemplate
{
//**********************************************************************************
/**
* Constructor for CertificateTemplate class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc templateID
*/
this.templateID = getParametersValue(parameters, "templateID", CertificateTemplate.defaultValues("templateID"));
if("templateMajorVersion" in parameters)
/**
* @type {number}
* @desc templateMajorVersion
*/
this.templateMajorVersion = getParametersValue(parameters, "templateMajorVersion", CertificateTemplate.defaultValues("templateMajorVersion"));
if("templateMinorVersion" in parameters)
/**
* @type {number}
* @desc templateMinorVersion
*/
this.templateMinorVersion = getParametersValue(parameters, "templateMinorVersion", CertificateTemplate.defaultValues("templateMinorVersion"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "templateID":
return "";
case "templateMajorVersion":
case "templateMinorVersion":
return 0;
default:
throw new Error(`Invalid member name for CertificateTemplate class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertificateTemplateOID ::= SEQUENCE {
* templateID OBJECT IDENTIFIER,
* templateMajorVersion INTEGER (0..4294967295) OPTIONAL,
* templateMinorVersion INTEGER (0..4294967295) OPTIONAL
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [templateID]
* @property {string} [templateMajorVersion]
* @property {string} [templateMinorVersion]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.templateID || "") }),
new asn1js.Integer({
name: (names.templateMajorVersion || ""),
optional: true
}),
new asn1js.Integer({
name: (names.templateMinorVersion || ""),
optional: true
}),
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"templateID",
"templateMajorVersion",
"templateMinorVersion"
]);
//endregion
//region Check the schema is valid
let asn1 = asn1js.compareSchema(schema,
schema,
CertificateTemplate.schema({
names: {
templateID: "templateID",
templateMajorVersion: "templateMajorVersion",
templateMinorVersion: "templateMinorVersion"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertificateTemplate");
//endregion
//region Get internal properties from parsed schema
this.templateID = asn1.result.templateID.valueBlock.toString();
if("templateMajorVersion" in asn1.result)
this.templateMajorVersion = asn1.result.templateMajorVersion.valueBlock.valueDec;
if("templateMinorVersion" in asn1.result)
this.templateMinorVersion = asn1.result.templateMinorVersion.valueBlock.valueDec;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.templateID }));
if("templateMajorVersion" in this)
outputArray.push(new asn1js.Integer({ value: this.templateMajorVersion }));
if("templateMinorVersion" in this)
outputArray.push(new asn1js.Integer({ value: this.templateMinorVersion }));
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
extnID: this.templateID
};
if("templateMajorVersion" in this)
object.templateMajorVersion = this.templateMajorVersion;
if("templateMinorVersion" in this)
object.templateMinorVersion = this.templateMinorVersion;
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,383 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, bufferToHexCodes, clearProps } from "./pvutils.js";
import { getEngine } from "./common.js";
import PublicKeyInfo from "./PublicKeyInfo.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import Attribute from "./Attribute.js";
//**************************************************************************************
function CertificationRequestInfo(parameters = {})
{
//CertificationRequestInfo ::= SEQUENCE {
// version INTEGER { v1(0) } (v1,...),
// subject Name,
// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
// attributes [0] Attributes{{ CRIAttributes }}
//}
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [CertificationRequestInfo]
* @property {string} [CertificationRequestInfoVersion]
* @property {string} [subject]
* @property {string} [CertificationRequestInfoAttributes]
* @property {string} [attributes]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.CertificationRequestInfo || "CertificationRequestInfo"),
value: [
new asn1js.Integer({ name: (names.CertificationRequestInfoVersion || "CertificationRequestInfo.version") }),
RelativeDistinguishedNames.schema(names.subject || {
names: {
blockName: "CertificationRequestInfo.subject"
}
}),
PublicKeyInfo.schema({
names: {
blockName: "CertificationRequestInfo.subjectPublicKeyInfo"
}
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Repeated({
optional: true, // Because OpenSSL makes wrong "attributes" field
name: (names.CertificationRequestInfoAttributes || "CertificationRequestInfo.attributes"),
value: Attribute.schema(names.attributes || {})
})
]
})
]
}));
}
//**************************************************************************************
/**
* Class from RFC2986
*/
export default class CertificationRequest
{
//**********************************************************************************
/**
* Constructor for Attribute class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {ArrayBuffer}
* @desc tbs
*/
this.tbs = getParametersValue(parameters, "tbs", CertificationRequest.defaultValues("tbs"));
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", CertificationRequest.defaultValues("version"));
/**
* @type {RelativeDistinguishedNames}
* @desc subject
*/
this.subject = getParametersValue(parameters, "subject", CertificationRequest.defaultValues("subject"));
/**
* @type {PublicKeyInfo}
* @desc subjectPublicKeyInfo
*/
this.subjectPublicKeyInfo = getParametersValue(parameters, "subjectPublicKeyInfo", CertificationRequest.defaultValues("subjectPublicKeyInfo"));
if("attributes" in parameters)
/**
* @type {Array.<Attribute>}
* @desc attributes
*/
this.attributes = getParametersValue(parameters, "attributes", CertificationRequest.defaultValues("attributes"));
/**
* @type {AlgorithmIdentifier}
* @desc signatureAlgorithm
*/
this.signatureAlgorithm = getParametersValue(parameters, "signatureAlgorithm", CertificationRequest.defaultValues("signatureAlgorithm"));
/**
* @type {BitString}
* @desc signatureAlgorithm
*/
this.signatureValue = getParametersValue(parameters, "signatureValue", CertificationRequest.defaultValues("signatureValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "tbs":
return new ArrayBuffer(0);
case "version":
return 0;
case "subject":
return new RelativeDistinguishedNames();
case "subjectPublicKeyInfo":
return new PublicKeyInfo();
case "attributes":
return [];
case "signatureAlgorithm":
return new AlgorithmIdentifier();
case "signatureValue":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for CertificationRequest class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* CertificationRequest ::= SEQUENCE {
* certificationRequestInfo CertificationRequestInfo,
* signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
* signature BIT STRING
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [certificationRequestInfo]
* @property {string} [signatureAlgorithm]
* @property {string} [signatureValue]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
value: [
CertificationRequestInfo(names.certificationRequestInfo || {}),
new asn1js.Sequence({
name: (names.signatureAlgorithm || "signatureAlgorithm"),
value: [
new asn1js.ObjectIdentifier(),
new asn1js.Any({ optional: true })
]
}),
new asn1js.BitString({ name: (names.signatureValue || "signatureValue") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"CertificationRequestInfo",
"CertificationRequestInfo.version",
"CertificationRequestInfo.subject",
"CertificationRequestInfo.subjectPublicKeyInfo",
"CertificationRequestInfo.attributes",
"signatureAlgorithm",
"signatureValue"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
CertificationRequest.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for CertificationRequest");
//endregion
//region Get internal properties from parsed schema
this.tbs = asn1.result.CertificationRequestInfo.valueBeforeDecode;
this.version = asn1.result["CertificationRequestInfo.version"].valueBlock.valueDec;
this.subject = new RelativeDistinguishedNames({ schema: asn1.result["CertificationRequestInfo.subject"] });
this.subjectPublicKeyInfo = new PublicKeyInfo({ schema: asn1.result["CertificationRequestInfo.subjectPublicKeyInfo"] });
if("CertificationRequestInfo.attributes" in asn1.result)
this.attributes = Array.from(asn1.result["CertificationRequestInfo.attributes"], element => new Attribute({ schema: element }));
this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.signatureAlgorithm });
this.signatureValue = asn1.result.signatureValue;
//endregion
}
//**********************************************************************************
/**
* Aux function making ASN1js Sequence from current TBS
* @returns {Sequence}
*/
encodeTBS()
{
//region Create array for output sequence
const outputArray = [
new asn1js.Integer({ value: this.version }),
this.subject.toSchema(),
this.subjectPublicKeyInfo.toSchema()
];
if("attributes" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: Array.from(this.attributes, element => element.toSchema())
}));
}
//endregion
return (new asn1js.Sequence({
value: outputArray
}));
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema(encodeFlag = false)
{
//region Decode stored TBS value
let tbsSchema;
if(encodeFlag === false)
{
if(this.tbs.byteLength === 0) // No stored TBS part
return CertificationRequest.schema();
tbsSchema = asn1js.fromBER(this.tbs).result;
}
//endregion
//region Create TBS schema via assembling from TBS parts
else
tbsSchema = this.encodeTBS();
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
tbsSchema,
this.signatureAlgorithm.toSchema(),
this.signatureValue
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
tbs: bufferToHexCodes(this.tbs, 0, this.tbs.byteLength),
version: this.version,
subject: this.subject.toJSON(),
subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(),
signatureAlgorithm: this.signatureAlgorithm.toJSON(),
signatureValue: this.signatureValue.toJSON()
};
if("attributes" in this)
object.attributes = Array.from(this.attributes, element => element.toJSON());
return object;
}
//**********************************************************************************
/**
* Makes signature for currect certification request
* @param {Object} privateKey WebCrypto private key
* @param {string} [hashAlgorithm=SHA-1] String representing current hashing algorithm
*/
sign(privateKey, hashAlgorithm = "SHA-1")
{
//region Initial checking
//region Get a private key from function parameter
if(typeof privateKey === "undefined")
return Promise.reject("Need to provide a private key for signing");
//endregion
//endregion
//region Initial variables
let sequence = Promise.resolve();
let parameters;
const engine = getEngine();
//endregion
//region Get a "default parameters" for current algorithm and set correct signature algorithm
sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
sequence = sequence.then(result =>
{
parameters = result.parameters;
this.signatureAlgorithm = result.signatureAlgorithm;
});
//endregion
//region Create TBS data for signing
sequence = sequence.then(() =>
{
this.tbs = this.encodeTBS().toBER(false);
});
//endregion
//region Signing TBS data on provided private key
sequence = sequence.then(() => engine.subtle.signWithPrivateKey(this.tbs, privateKey, parameters));
sequence = sequence.then(result =>
{
this.signatureValue = new asn1js.BitString({ valueHex: result });
});
//endregion
return sequence;
}
//**********************************************************************************
/**
* Verify existing certification request signature
* @returns {*}
*/
verify()
{
return getEngine().subtle.verifyWithPublicKey(this.tbs, this.signatureValue, this.subjectPublicKeyInfo, this.signatureAlgorithm);
}
//**********************************************************************************
/**
* Importing public key for current certificate request
*/
getPublicKey(parameters = null)
{
return getEngine().getPublicKey(this.subjectPublicKeyInfo, this.signatureAlgorithm, parameters);
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,181 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class ContentInfo
{
//**********************************************************************************
/**
* Constructor for ContentInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc contentType
*/
this.contentType = getParametersValue(parameters, "contentType", ContentInfo.defaultValues("contentType"));
/**
* @type {Any}
* @desc content
*/
this.content = getParametersValue(parameters, "content", ContentInfo.defaultValues("content"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "contentType":
return "";
case "content":
return new asn1js.Any();
default:
throw new Error(`Invalid member name for ContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "contentType":
return (memberValue === "");
case "content":
return (memberValue instanceof asn1js.Any);
default:
throw new Error(`Invalid member name for ContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content [0] EXPLICIT ANY DEFINED BY contentType }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [contentType]
* @property {string} [content]
*/
const names = getParametersValue(parameters, "names", {});
if(("optional" in names) === false)
names.optional = false;
return (new asn1js.Sequence({
name: (names.blockName || "ContentInfo"),
optional: names.optional,
value: [
new asn1js.ObjectIdentifier({ name: (names.contentType || "contentType") }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [new asn1js.Any({ name: (names.content || "content") })] // EXPLICIT ANY value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"contentType",
"content"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
ContentInfo.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for ContentInfo");
//endregion
//region Get internal properties from parsed schema
this.contentType = asn1.result.contentType.valueBlock.toString();
this.content = asn1.result.content;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.contentType }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.content] // EXPLICIT ANY value
})
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
contentType: this.contentType
};
if(!(this.content instanceof asn1js.Any))
object.content = this.content.toJSON();
return object;
}
//**********************************************************************************
}
//**************************************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -1,179 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC3447
*/
export default class DigestInfo
{
//**********************************************************************************
/**
* Constructor for DigestInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AlgorithmIdentifier}
* @desc digestAlgorithm
*/
this.digestAlgorithm = getParametersValue(parameters, "digestAlgorithm", DigestInfo.defaultValues("digestAlgorithm"));
/**
* @type {OctetString}
* @desc digest
*/
this.digest = getParametersValue(parameters, "digest", DigestInfo.defaultValues("digest"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "digestAlgorithm":
return new AlgorithmIdentifier();
case "digest":
return new asn1js.OctetString();
default:
throw new Error(`Invalid member name for DigestInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "digestAlgorithm":
return ((AlgorithmIdentifier.compareWithDefault("algorithmId", memberValue.algorithmId)) &&
(("algorithmParams" in memberValue) === false));
case "digest":
return (memberValue.isEqual(DigestInfo.defaultValues(memberName)));
default:
throw new Error(`Invalid member name for DigestInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* Digest ::= OCTET STRING
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [type]
* @property {string} [setName]
* @property {string} [values]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AlgorithmIdentifier.schema(names.digestAlgorithm || {
names: {
blockName: "digestAlgorithm"
}
}),
new asn1js.OctetString({ name: (names.digest || "digest") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"digestAlgorithm",
"digest"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
DigestInfo.schema({
names: {
digestAlgorithm: {
names: {
blockName: "digestAlgorithm"
}
},
digest: "digest"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for DigestInfo");
//endregion
//region Get internal properties from parsed schema
this.digestAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.digestAlgorithm });
this.digest = asn1.result.digest;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
this.digestAlgorithm.toSchema(),
this.digest
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
digestAlgorithm: this.digestAlgorithm.toJSON(),
digest: this.digest.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,334 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class DistributionPoint
{
//**********************************************************************************
/**
* Constructor for DistributionPoint class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
* @property {Object} [distributionPoint]
* @property {Object} [reasons]
* @property {Object} [cRLIssuer]
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("distributionPoint" in parameters)
/**
* @type {Array.<GeneralName>}
* @desc distributionPoint
*/
this.distributionPoint = getParametersValue(parameters, "distributionPoint", DistributionPoint.defaultValues("distributionPoint"));
if("reasons" in parameters)
/**
* @type {BitString}
* @desc values
*/
this.reasons = getParametersValue(parameters, "reasons", DistributionPoint.defaultValues("reasons"));
if("cRLIssuer" in parameters)
/**
* @type {Array.<GeneralName>}
* @desc cRLIssuer
*/
this.cRLIssuer = getParametersValue(parameters, "cRLIssuer", DistributionPoint.defaultValues("cRLIssuer"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "distributionPoint":
return [];
case "reasons":
return new asn1js.BitString();
case "cRLIssuer":
return [];
default:
throw new Error(`Invalid member name for DistributionPoint class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* DistributionPoint ::= SEQUENCE {
* distributionPoint [0] DistributionPointName OPTIONAL,
* reasons [1] ReasonFlags OPTIONAL,
* cRLIssuer [2] GeneralNames OPTIONAL }
*
* DistributionPointName ::= CHOICE {
* fullName [0] GeneralNames,
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
*
* ReasonFlags ::= BIT STRING {
* unused (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6),
* privilegeWithdrawn (7),
* aACompromise (8) }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [distributionPoint]
* @property {string} [distributionPointNames]
* @property {string} [reasons]
* @property {string} [cRLIssuer]
* @property {string} [cRLIssuerNames]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Choice({
value: [
new asn1js.Constructed({
name: (names.distributionPoint || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Repeated({
name: (names.distributionPointNames || ""),
value: GeneralName.schema()
})
]
}),
new asn1js.Constructed({
name: (names.distributionPoint || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: RelativeDistinguishedNames.schema().valueBlock.value
})
]
})
]
}),
new asn1js.Primitive({
name: (names.reasons || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
}
}), // IMPLICIT bitstring value
new asn1js.Constructed({
name: (names.cRLIssuer || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
value: [
new asn1js.Repeated({
name: (names.cRLIssuerNames || ""),
value: GeneralName.schema()
})
]
}) // IMPLICIT bitstring value
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"distributionPoint",
"distributionPointNames",
"reasons",
"cRLIssuer",
"cRLIssuerNames"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
DistributionPoint.schema({
names: {
distributionPoint: "distributionPoint",
distributionPointNames: "distributionPointNames",
reasons: "reasons",
cRLIssuer: "cRLIssuer",
cRLIssuerNames: "cRLIssuerNames"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for DistributionPoint");
//endregion
//region Get internal properties from parsed schema
if("distributionPoint" in asn1.result)
{
if(asn1.result.distributionPoint.idBlock.tagNumber === 0) // GENERAL_NAMES variant
this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new GeneralName({ schema: element }));
if(asn1.result.distributionPoint.idBlock.tagNumber === 1) // RDN variant
{
this.distributionPoint = new RelativeDistinguishedNames({
schema: new asn1js.Sequence({
value: asn1.result.distributionPoint.valueBlock.value
})
});
}
}
if("reasons" in asn1.result)
this.reasons = new asn1js.BitString({ valueHex: asn1.result.reasons.valueBlock.valueHex });
if("cRLIssuer" in asn1.result)
this.cRLIssuer = Array.from(asn1.result.cRLIssuerNames, element => new GeneralName({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if("distributionPoint" in this)
{
let internalValue;
if(this.distributionPoint instanceof Array)
{
internalValue = new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: Array.from(this.distributionPoint, element => element.toSchema())
});
}
else
{
internalValue = new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [this.distributionPoint.toSchema()]
});
}
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [internalValue]
}));
}
if("reasons" in this)
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
valueHex: this.reasons.valueBlock.valueHex
}));
}
if("cRLIssuer" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
value: Array.from(this.cRLIssuer, element => element.toSchema())
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if("distributionPoint" in this)
{
if(this.distributionPoint instanceof Array)
object.distributionPoint = Array.from(this.distributionPoint, element => element.toJSON());
else
object.distributionPoint = this.distributionPoint.toJSON();
}
if("reasons" in this)
object.reasons = this.reasons.toJSON();
if("cRLIssuer" in this)
object.cRLIssuer = Array.from(this.cRLIssuer, element => element.toJSON());
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,233 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC6318
*/
export default class ECCCMSSharedInfo
{
//**********************************************************************************
/**
* Constructor for ECCCMSSharedInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AlgorithmIdentifier}
* @desc keyInfo
*/
this.keyInfo = getParametersValue(parameters, "keyInfo", ECCCMSSharedInfo.defaultValues("keyInfo"));
if("entityUInfo" in parameters)
/**
* @type {OctetString}
* @desc entityUInfo
*/
this.entityUInfo = getParametersValue(parameters, "entityUInfo", ECCCMSSharedInfo.defaultValues("entityUInfo"));
/**
* @type {OctetString}
* @desc suppPubInfo
*/
this.suppPubInfo = getParametersValue(parameters, "suppPubInfo", ECCCMSSharedInfo.defaultValues("suppPubInfo"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "keyInfo":
return new AlgorithmIdentifier();
case "entityUInfo":
return new asn1js.OctetString();
case "suppPubInfo":
return new asn1js.OctetString();
default:
throw new Error(`Invalid member name for ECCCMSSharedInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "keyInfo":
case "entityUInfo":
case "suppPubInfo":
return (memberValue.isEqual(ECCCMSSharedInfo.defaultValues(memberName)));
default:
throw new Error(`Invalid member name for ECCCMSSharedInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* ECC-CMS-SharedInfo ::= SEQUENCE {
* keyInfo AlgorithmIdentifier,
* entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL,
* suppPubInfo [2] EXPLICIT OCTET STRING }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [keyInfo]
* @property {string} [entityUInfo]
* @property {string} [suppPubInfo]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AlgorithmIdentifier.schema(names.keyInfo || {}),
new asn1js.Constructed({
name: (names.entityUInfo || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
optional: true,
value: [new asn1js.OctetString()]
}),
new asn1js.Constructed({
name: (names.suppPubInfo || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
value: [new asn1js.OctetString()]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"keyInfo",
"entityUInfo",
"suppPubInfo"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
ECCCMSSharedInfo.schema({
names: {
keyInfo: {
names: {
blockName: "keyInfo"
}
},
entityUInfo: "entityUInfo",
suppPubInfo: "suppPubInfo"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for ECCCMSSharedInfo");
//endregion
//region Get internal properties from parsed schema
this.keyInfo = new AlgorithmIdentifier({ schema: asn1.result.keyInfo });
if("entityUInfo" in asn1.result)
this.entityUInfo = asn1.result.entityUInfo.valueBlock.value[0];
this.suppPubInfo = asn1.result.suppPubInfo.valueBlock.value[0];
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create output array for sequence
const outputArray = [];
outputArray.push(this.keyInfo.toSchema());
if("entityUInfo" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.entityUInfo]
}));
}
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
value: [this.suppPubInfo]
}));
//endregion
//region Construct and return new ASN.1 schema for this object
return new asn1js.Sequence({
value: outputArray
});
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
keyInfo: this.keyInfo.toJSON()
};
if("entityUInfo" in this)
_object.entityUInfo = this.entityUInfo.toJSON();
_object.suppPubInfo = this.suppPubInfo.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,344 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, toBase64, arrayBufferToString, stringToArrayBuffer, fromBase64, clearProps } from "./pvutils.js";
import ECPublicKey from "./ECPublicKey.js";
//**************************************************************************************
/**
* Class from RFC5915
*/
export default class ECPrivateKey
{
//**********************************************************************************
/**
* Constructor for ECPrivateKey class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", ECPrivateKey.defaultValues("version"));
/**
* @type {OctetString}
* @desc privateKey
*/
this.privateKey = getParametersValue(parameters, "privateKey", ECPrivateKey.defaultValues("privateKey"));
if("namedCurve" in parameters)
/**
* @type {string}
* @desc namedCurve
*/
this.namedCurve = getParametersValue(parameters, "namedCurve", ECPrivateKey.defaultValues("namedCurve"));
if("publicKey" in parameters)
/**
* @type {ECPublicKey}
* @desc publicKey
*/
this.publicKey = getParametersValue(parameters, "publicKey", ECPrivateKey.defaultValues("publicKey"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
//region If input argument array contains "json" for this object
if("json" in parameters)
this.fromJSON(parameters.json);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return 1;
case "privateKey":
return new asn1js.OctetString();
case "namedCurve":
return "";
case "publicKey":
return new ECPublicKey();
default:
throw new Error(`Invalid member name for ECCPrivateKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "version":
return (memberValue === ECPrivateKey.defaultValues(memberName));
case "privateKey":
return (memberValue.isEqual(ECPrivateKey.defaultValues(memberName)));
case "namedCurve":
return (memberValue === "");
case "publicKey":
return ((ECPublicKey.compareWithDefault("namedCurve", memberValue.namedCurve)) &&
(ECPublicKey.compareWithDefault("x", memberValue.x)) &&
(ECPublicKey.compareWithDefault("y", memberValue.y)));
default:
throw new Error(`Invalid member name for ECCPrivateKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* ECPrivateKey ::= SEQUENCE {
* version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
* privateKey OCTET STRING,
* parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
* publicKey [1] BIT STRING OPTIONAL
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [version]
* @property {string} [privateKey]
* @property {string} [namedCurve]
* @property {string} [publicKey]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Integer({ name: (names.version || "") }),
new asn1js.OctetString({ name: (names.privateKey || "") }),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.ObjectIdentifier({ name: (names.namedCurve || "") })
]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.BitString({ name: (names.publicKey || "") })
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"privateKey",
"namedCurve",
"publicKey"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
ECPrivateKey.schema({
names: {
version: "version",
privateKey: "privateKey",
namedCurve: "namedCurve",
publicKey: "publicKey"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for ECPrivateKey");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
this.privateKey = asn1.result.privateKey;
if("namedCurve" in asn1.result)
this.namedCurve = asn1.result.namedCurve.valueBlock.toString();
if("publicKey" in asn1.result)
{
const publicKeyData = { schema: asn1.result.publicKey.valueBlock.valueHex };
if("namedCurve" in this)
publicKeyData.namedCurve = this.namedCurve;
this.publicKey = new ECPublicKey(publicKeyData);
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
const outputArray = [
new asn1js.Integer({ value: this.version }),
this.privateKey
];
if("namedCurve" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.ObjectIdentifier({ value: this.namedCurve })
]
}));
}
if("publicKey" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.BitString({ valueHex: this.publicKey.toSchema().toBER(false) })
]
}));
}
return new asn1js.Sequence({
value: outputArray
});
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
if((("namedCurve" in this) === false) || (ECPrivateKey.compareWithDefault("namedCurve", this.namedCurve)))
throw new Error("Not enough information for making JSON: absent \"namedCurve\" value");
let crvName = "";
switch(this.namedCurve)
{
case "1.2.840.10045.3.1.7": // P-256
crvName = "P-256";
break;
case "1.3.132.0.34": // P-384
crvName = "P-384";
break;
case "1.3.132.0.35": // P-521
crvName = "P-521";
break;
default:
}
const privateKeyJSON = {
crv: crvName,
d: toBase64(arrayBufferToString(this.privateKey.valueBlock.valueHex), true, true, false)
};
if("publicKey" in this)
{
const publicKeyJSON = this.publicKey.toJSON();
privateKeyJSON.x = publicKeyJSON.x;
privateKeyJSON.y = publicKeyJSON.y;
}
return privateKeyJSON;
}
//**********************************************************************************
/**
* Convert JSON value into current object
* @param {Object} json
*/
fromJSON(json)
{
let coodinateLength = 0;
if("crv" in json)
{
switch(json.crv.toUpperCase())
{
case "P-256":
this.namedCurve = "1.2.840.10045.3.1.7";
coodinateLength = 32;
break;
case "P-384":
this.namedCurve = "1.3.132.0.34";
coodinateLength = 48;
break;
case "P-521":
this.namedCurve = "1.3.132.0.35";
coodinateLength = 66;
break;
default:
}
}
else
throw new Error("Absent mandatory parameter \"crv\"");
if("d" in json)
{
const convertBuffer = stringToArrayBuffer(fromBase64(json.d, true));
if(convertBuffer.byteLength < coodinateLength)
{
const buffer = new ArrayBuffer(coodinateLength);
const view = new Uint8Array(buffer);
const convertBufferView = new Uint8Array(convertBuffer);
view.set(convertBufferView, 1);
this.privateKey = new asn1js.OctetString({ valueHex: buffer });
}
else
this.privateKey = new asn1js.OctetString({ valueHex: convertBuffer.slice(0, coodinateLength) });
}
else
throw new Error("Absent mandatory parameter \"d\"");
if(("x" in json) && ("y" in json))
this.publicKey = new ECPublicKey({ json });
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,242 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, utilConcatBuf, isEqualBuffer, toBase64, fromBase64, arrayBufferToString, stringToArrayBuffer } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5480
*/
export default class ECPublicKey
{
//**********************************************************************************
/**
* Constructor for ECCPublicKey class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {ArrayBuffer}
* @desc type
*/
this.x = getParametersValue(parameters, "x", ECPublicKey.defaultValues("x"));
/**
* @type {ArrayBuffer}
* @desc values
*/
this.y = getParametersValue(parameters, "y", ECPublicKey.defaultValues("y"));
/**
* @type {string}
* @desc namedCurve
*/
this.namedCurve = getParametersValue(parameters, "namedCurve", ECPublicKey.defaultValues("namedCurve"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
//region If input argument array contains "json" for this object
if("json" in parameters)
this.fromJSON(parameters.json);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "x":
case "y":
return new ArrayBuffer(0);
case "namedCurve":
return "";
default:
throw new Error(`Invalid member name for ECCPublicKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "x":
case "y":
return (isEqualBuffer(memberValue, ECPublicKey.defaultValues(memberName)));
case "namedCurve":
return (memberValue === "");
default:
throw new Error(`Invalid member name for ECCPublicKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
return new asn1js.RawData();
}
//**********************************************************************************
/**
* Convert ArrayBuffer into current class
* @param {!ArrayBuffer} schema Special case: schema is an ArrayBuffer
*/
fromSchema(schema)
{
//region Check the schema is valid
if((schema instanceof ArrayBuffer) === false)
throw new Error("Object's schema was not verified against input data for ECPublicKey");
const view = new Uint8Array(schema);
if(view[0] !== 0x04)
throw new Error("Object's schema was not verified against input data for ECPublicKey");
//endregion
//region Get internal properties from parsed schema
let coordinateLength;
switch(this.namedCurve)
{
case "1.2.840.10045.3.1.7": // P-256
coordinateLength = 32;
break;
case "1.3.132.0.34": // P-384
coordinateLength = 48;
break;
case "1.3.132.0.35": // P-521
coordinateLength = 66;
break;
default:
throw new Error(`Incorrect curve OID: ${this.namedCurve}`);
}
if(schema.byteLength !== (coordinateLength * 2 + 1))
throw new Error("Object's schema was not verified against input data for ECPublicKey");
this.x = schema.slice(1, coordinateLength + 1);
this.y = schema.slice(1 + coordinateLength, coordinateLength * 2 + 1);
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
return new asn1js.RawData({ data: utilConcatBuf(
(new Uint8Array([0x04])).buffer,
this.x,
this.y
)
});
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
let crvName = "";
switch(this.namedCurve)
{
case "1.2.840.10045.3.1.7": // P-256
crvName = "P-256";
break;
case "1.3.132.0.34": // P-384
crvName = "P-384";
break;
case "1.3.132.0.35": // P-521
crvName = "P-521";
break;
default:
}
return {
crv: crvName,
x: toBase64(arrayBufferToString(this.x), true, true, false),
y: toBase64(arrayBufferToString(this.y), true, true, false)
};
}
//**********************************************************************************
/**
* Convert JSON value into current object
* @param {Object} json
*/
fromJSON(json)
{
let coodinateLength = 0;
if("crv" in json)
{
switch(json.crv.toUpperCase())
{
case "P-256":
this.namedCurve = "1.2.840.10045.3.1.7";
coodinateLength = 32;
break;
case "P-384":
this.namedCurve = "1.3.132.0.34";
coodinateLength = 48;
break;
case "P-521":
this.namedCurve = "1.3.132.0.35";
coodinateLength = 66;
break;
default:
}
}
else
throw new Error("Absent mandatory parameter \"crv\"");
if("x" in json)
{
const convertBuffer = stringToArrayBuffer(fromBase64(json.x, true));
if(convertBuffer.byteLength < coodinateLength)
{
this.x = new ArrayBuffer(coodinateLength);
const view = new Uint8Array(this.x);
const convertBufferView = new Uint8Array(convertBuffer);
view.set(convertBufferView, 1);
}
else
this.x = convertBuffer.slice(0, coodinateLength);
}
else
throw new Error("Absent mandatory parameter \"x\"");
if("y" in json)
{
const convertBuffer = stringToArrayBuffer(fromBase64(json.y, true));
if(convertBuffer.byteLength < coodinateLength)
{
this.y = new ArrayBuffer(coodinateLength);
const view = new Uint8Array(this.y);
const convertBufferView = new Uint8Array(convertBuffer);
view.set(convertBufferView, 1);
}
else
this.y = convertBuffer.slice(0, coodinateLength);
}
else
throw new Error("Absent mandatory parameter \"y\"");
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,243 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class EncapsulatedContentInfo
{
//**********************************************************************************
/**
* Constructor for EncapsulatedContentInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc eContentType
*/
this.eContentType = getParametersValue(parameters, "eContentType", EncapsulatedContentInfo.defaultValues("eContentType"));
if("eContent" in parameters)
{
/**
* @type {OctetString}
* @desc eContent
*/
this.eContent = getParametersValue(parameters, "eContent", EncapsulatedContentInfo.defaultValues("eContent"));
if((this.eContent.idBlock.tagClass === 1) &&
(this.eContent.idBlock.tagNumber === 4))
{
//region Divide OCTETSTRING value down to small pieces
if(this.eContent.idBlock.isConstructed === false)
{
const constrString = new asn1js.OctetString({
idBlock: { isConstructed: true },
isConstructed: true
});
let offset = 0;
let length = this.eContent.valueBlock.valueHex.byteLength;
while(length > 0)
{
const pieceView = new Uint8Array(this.eContent.valueBlock.valueHex, offset, ((offset + 65536) > this.eContent.valueBlock.valueHex.byteLength) ? (this.eContent.valueBlock.valueHex.byteLength - offset) : 65536);
const _array = new ArrayBuffer(pieceView.length);
const _view = new Uint8Array(_array);
for(let i = 0; i < _view.length; i++)
_view[i] = pieceView[i];
constrString.valueBlock.value.push(new asn1js.OctetString({ valueHex: _array }));
length -= pieceView.length;
offset += pieceView.length;
}
this.eContent = constrString;
}
//endregion
}
}
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "eContentType":
return "";
case "eContent":
return new asn1js.OctetString();
default:
throw new Error(`Invalid member name for EncapsulatedContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "eContentType":
return (memberValue === "");
case "eContent":
{
if((memberValue.idBlock.tagClass === 1) && (memberValue.idBlock.tagNumber === 4))
return (memberValue.isEqual(EncapsulatedContentInfo.defaultValues("eContent")));
return false;
}
default:
throw new Error(`Invalid member name for EncapsulatedContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* EncapsulatedContentInfo ::= SEQUENCE {
* eContentType ContentType,
* eContent [0] EXPLICIT OCTET STRING OPTIONAL } * Changed it to ANY, as in PKCS#7
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [type]
* @property {string} [setName]
* @property {string} [values]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.eContentType || "") }),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Any({ name: (names.eContent || "") }) // In order to aling this with PKCS#7 and CMS as well
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"eContentType",
"eContent"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
EncapsulatedContentInfo.schema({
names: {
eContentType: "eContentType",
eContent: "eContent"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for EncapsulatedContentInfo");
//endregion
//region Get internal properties from parsed schema
this.eContentType = asn1.result.eContentType.valueBlock.toString();
if("eContent" in asn1.result)
this.eContent = asn1.result.eContent;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.eContentType }));
if("eContent" in this)
{
if(EncapsulatedContentInfo.compareWithDefault("eContent", this.eContent) === false)
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.eContent]
}));
}
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
eContentType: this.eContentType
};
if("eContent" in this)
{
if(EncapsulatedContentInfo.compareWithDefault("eContent", this.eContent) === false)
_object.eContent = this.eContent.toJSON();
}
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,287 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class EncryptedContentInfo
{
//**********************************************************************************
/**
* Constructor for EncryptedContentInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc contentType
*/
this.contentType = getParametersValue(parameters, "contentType", EncryptedContentInfo.defaultValues("contentType"));
/**
* @type {AlgorithmIdentifier}
* @desc contentEncryptionAlgorithm
*/
this.contentEncryptionAlgorithm = getParametersValue(parameters, "contentEncryptionAlgorithm", EncryptedContentInfo.defaultValues("contentEncryptionAlgorithm"));
if("encryptedContent" in parameters)
{
/**
* @type {OctetString}
* @desc encryptedContent (!!!) could be contructive or primitive value (!!!)
*/
this.encryptedContent = parameters.encryptedContent;
if((this.encryptedContent.idBlock.tagClass === 1) &&
(this.encryptedContent.idBlock.tagNumber === 4))
{
//region Divide OCTETSTRING value down to small pieces
if(this.encryptedContent.idBlock.isConstructed === false)
{
const constrString = new asn1js.OctetString({
idBlock: { isConstructed: true },
isConstructed: true
});
let offset = 0;
let length = this.encryptedContent.valueBlock.valueHex.byteLength;
while(length > 0)
{
const pieceView = new Uint8Array(this.encryptedContent.valueBlock.valueHex, offset, ((offset + 1024) > this.encryptedContent.valueBlock.valueHex.byteLength) ? (this.encryptedContent.valueBlock.valueHex.byteLength - offset) : 1024);
const _array = new ArrayBuffer(pieceView.length);
const _view = new Uint8Array(_array);
for(let i = 0; i < _view.length; i++)
_view[i] = pieceView[i];
constrString.valueBlock.value.push(new asn1js.OctetString({ valueHex: _array }));
length -= pieceView.length;
offset += pieceView.length;
}
this.encryptedContent = constrString;
}
//endregion
}
}
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "contentType":
return "";
case "contentEncryptionAlgorithm":
return new AlgorithmIdentifier();
case "encryptedContent":
return new asn1js.OctetString();
default:
throw new Error(`Invalid member name for EncryptedContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "contentType":
return (memberValue === "");
case "contentEncryptionAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "encryptedContent":
return (memberValue.isEqual(EncryptedContentInfo.defaultValues(memberName)));
default:
throw new Error(`Invalid member name for EncryptedContentInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* EncryptedContentInfo ::= SEQUENCE {
* contentType ContentType,
* contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
*
* Comment: Strange, but modern crypto engines create "encryptedContent" as "[0] EXPLICIT EncryptedContent"
*
* EncryptedContent ::= OCTET STRING
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [contentType]
* @property {string} [contentEncryptionAlgorithm]
* @property {string} [encryptedContent]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.contentType || "") }),
AlgorithmIdentifier.schema(names.contentEncryptionAlgorithm || {}),
// The CHOICE we need because "EncryptedContent" could have either "constructive"
// or "primitive" form of encoding and we need to handle both variants
new asn1js.Choice({
value: [
new asn1js.Constructed({
name: (names.encryptedContent || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Repeated({
value: new asn1js.OctetString()
})
]
}),
new asn1js.Primitive({
name: (names.encryptedContent || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
}
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"contentType",
"contentEncryptionAlgorithm",
"encryptedContent"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
EncryptedContentInfo.schema({
names: {
contentType: "contentType",
contentEncryptionAlgorithm: {
names: {
blockName: "contentEncryptionAlgorithm"
}
},
encryptedContent: "encryptedContent"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for EncryptedContentInfo");
//endregion
//region Get internal properties from parsed schema
this.contentType = asn1.result.contentType.valueBlock.toString();
this.contentEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.contentEncryptionAlgorithm });
if("encryptedContent" in asn1.result)
{
this.encryptedContent = asn1.result.encryptedContent;
this.encryptedContent.idBlock.tagClass = 1; // UNIVERSAL
this.encryptedContent.idBlock.tagNumber = 4; // OCTETSTRING (!!!) The value still has instance of "in_window.org.pkijs.asn1.ASN1_CONSTRUCTED / ASN1_PRIMITIVE"
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const sequenceLengthBlock = {
isIndefiniteForm: false
};
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.contentType }));
outputArray.push(this.contentEncryptionAlgorithm.toSchema());
if("encryptedContent" in this)
{
sequenceLengthBlock.isIndefiniteForm = this.encryptedContent.idBlock.isConstructed;
const encryptedValue = this.encryptedContent;
encryptedValue.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
encryptedValue.idBlock.tagNumber = 0; // [0]
encryptedValue.lenBlock.isIndefiniteForm = this.encryptedContent.idBlock.isConstructed;
outputArray.push(encryptedValue);
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
lenBlock: sequenceLengthBlock,
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
contentType: this.contentType,
contentEncryptionAlgorithm: this.contentEncryptionAlgorithm.toJSON()
};
if("encryptedContent" in this)
_object.encryptedContent = this.encryptedContent.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,287 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import { getEngine } from "./common.js";
import EncryptedContentInfo from "./EncryptedContentInfo.js";
import Attribute from "./Attribute.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class EncryptedData
{
//**********************************************************************************
/**
* Constructor for EncryptedData class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", EncryptedData.defaultValues("version"));
/**
* @type {EncryptedContentInfo}
* @desc encryptedContentInfo
*/
this.encryptedContentInfo = getParametersValue(parameters, "encryptedContentInfo", EncryptedData.defaultValues("encryptedContentInfo"));
if("unprotectedAttrs" in parameters)
/**
* @type {Array.<Attribute>}
* @desc unprotectedAttrs
*/
this.unprotectedAttrs = getParametersValue(parameters, "unprotectedAttrs", EncryptedData.defaultValues("unprotectedAttrs"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return 0;
case "encryptedContentInfo":
return new EncryptedContentInfo();
case "unprotectedAttrs":
return [];
default:
throw new Error(`Invalid member name for EncryptedData class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "version":
return (memberValue === 0);
case "encryptedContentInfo":
return ((EncryptedContentInfo.compareWithDefault("contentType", memberValue.contentType)) &&
(EncryptedContentInfo.compareWithDefault("contentEncryptionAlgorithm", memberValue.contentEncryptionAlgorithm)) &&
(EncryptedContentInfo.compareWithDefault("encryptedContent", memberValue.encryptedContent)));
case "unprotectedAttrs":
return (memberValue.length === 0);
default:
throw new Error(`Invalid member name for EncryptedData class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* EncryptedData ::= SEQUENCE {
* version CMSVersion,
* encryptedContentInfo EncryptedContentInfo,
* unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [version]
* @property {string} [encryptedContentInfo]
* @property {string} [unprotectedAttrs]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Integer({ name: (names.version || "") }),
EncryptedContentInfo.schema(names.encryptedContentInfo || {}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.Repeated({
name: (names.unprotectedAttrs || ""),
value: Attribute.schema()
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"encryptedContentInfo",
"unprotectedAttrs"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
EncryptedData.schema({
names: {
version: "version",
encryptedContentInfo: {
names: {
blockName: "encryptedContentInfo"
}
},
unprotectedAttrs: "unprotectedAttrs"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for EncryptedData");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
this.encryptedContentInfo = new EncryptedContentInfo({ schema: asn1.result.encryptedContentInfo });
if("unprotectedAttrs" in asn1.result)
this.unprotectedAttrs = Array.from(asn1.result.unprotectedAttrs, element => new Attribute({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.Integer({ value: this.version }));
outputArray.push(this.encryptedContentInfo.toSchema());
if("unprotectedAttrs" in this)
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: Array.from(this.unprotectedAttrs, element => element.toSchema())
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
version: this.version,
encryptedContentInfo: this.encryptedContentInfo.toJSON()
};
if("unprotectedAttrs" in this)
_object.unprotectedAttrs = Array.from(this.unprotectedAttrs, element => element.toJSON());
return _object;
}
//**********************************************************************************
/**
* Create a new CMS Encrypted Data content
* @param {Object} parameters Parameters neccessary for encryption
* @returns {Promise}
*/
encrypt(parameters)
{
//region Check for input parameters
if((parameters instanceof Object) === false)
return Promise.reject("Parameters must have type \"Object\"");
//endregion
//region Get cryptographic engine
const engine = getEngine();
if(typeof engine === "undefined")
return Promise.reject("Unable to initialize cryptographic engine");
//endregion
//region Set "contentType" parameter
parameters.contentType = "1.2.840.113549.1.7.1"; // "data"
//endregion
if("encryptEncryptedContentInfo" in engine.subtle)
{
return engine.subtle.encryptEncryptedContentInfo(parameters).then(result =>
{
this.encryptedContentInfo = result;
});
}
return Promise.reject(`No support for "encryptEncryptedContentInfo" in current crypto engine ${engine.name}`);
}
//**********************************************************************************
/**
* Create a new CMS Encrypted Data content
* @param {Object} parameters Parameters neccessary for encryption
*/
decrypt(parameters)
{
//region Check for input parameters
if((parameters instanceof Object) === false)
return Promise.reject("Parameters must have type \"Object\"");
//endregion
//region Get cryptographic engine
const engine = getEngine();
if(typeof engine === "undefined")
return Promise.reject("Unable to initialize cryptographic engine");
//endregion
//region Set "encryptedContentInfo" value
parameters.encryptedContentInfo = this.encryptedContentInfo;
//endregion
if("decryptEncryptedContentInfo" in engine.subtle)
return engine.subtle.decryptEncryptedContentInfo(parameters);
return Promise.reject(`No support for "decryptEncryptedContentInfo" in current crypto engine ${engine.name}`);
}
//**********************************************************************************
}
//**************************************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -1,135 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class ExtKeyUsage
{
//**********************************************************************************
/**
* Constructor for ExtKeyUsage class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<string>}
* @desc keyPurposes
*/
this.keyPurposes = getParametersValue(parameters, "keyPurposes", ExtKeyUsage.defaultValues("keyPurposes"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "keyPurposes":
return [];
default:
throw new Error(`Invalid member name for ExtKeyUsage class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* ExtKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
*
* KeyPurposeId ::= OBJECT IDENTIFIER
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [keyPurposes]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.keyPurposes || ""),
value: new asn1js.ObjectIdentifier()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"keyPurposes"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
ExtKeyUsage.schema({
names: {
keyPurposes: "keyPurposes"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for ExtKeyUsage");
//endregion
//region Get internal properties from parsed schema
this.keyPurposes = Array.from(asn1.result.keyPurposes, element => element.valueBlock.toString());
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.keyPurposes, element => new asn1js.ObjectIdentifier({ value: element }))
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
keyPurposes: Array.from(this.keyPurposes)
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,453 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import SubjectDirectoryAttributes from "./SubjectDirectoryAttributes.js";
import PrivateKeyUsagePeriod from "./PrivateKeyUsagePeriod.js";
import AltName from "./AltName.js";
import BasicConstraints from "./BasicConstraints.js";
import IssuingDistributionPoint from "./IssuingDistributionPoint.js";
import GeneralNames from "./GeneralNames.js";
import NameConstraints from "./NameConstraints.js";
import CRLDistributionPoints from "./CRLDistributionPoints.js";
import CertificatePolicies from "./CertificatePolicies.js";
import PolicyMappings from "./PolicyMappings.js";
import AuthorityKeyIdentifier from "./AuthorityKeyIdentifier.js";
import PolicyConstraints from "./PolicyConstraints.js";
import ExtKeyUsage from "./ExtKeyUsage.js";
import InfoAccess from "./InfoAccess.js";
import SignedCertificateTimestampList from "./SignedCertificateTimestampList.js";
import CertificateTemplate from "./CertificateTemplate.js";
import CAVersion from "./CAVersion.js";
import QCStatements from "./QCStatements.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class Extension
{
//**********************************************************************************
/**
* Constructor for Extension class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc extnID
*/
this.extnID = getParametersValue(parameters, "extnID", Extension.defaultValues("extnID"));
/**
* @type {boolean}
* @desc critical
*/
this.critical = getParametersValue(parameters, "critical", Extension.defaultValues("critical"));
/**
* @type {OctetString}
* @desc extnValue
*/
if("extnValue" in parameters)
this.extnValue = new asn1js.OctetString({ valueHex: parameters.extnValue });
else
this.extnValue = Extension.defaultValues("extnValue");
if("parsedValue" in parameters)
/**
* @type {Object}
* @desc parsedValue
*/
this.parsedValue = getParametersValue(parameters, "parsedValue", Extension.defaultValues("parsedValue"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "extnID":
return "";
case "critical":
return false;
case "extnValue":
return new asn1js.OctetString();
case "parsedValue":
return {};
default:
throw new Error(`Invalid member name for Extension class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* Extension ::= SEQUENCE {
* extnID OBJECT IDENTIFIER,
* critical BOOLEAN DEFAULT FALSE,
* extnValue OCTET STRING
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [extnID]
* @property {string} [critical]
* @property {string} [extnValue]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.extnID || "") }),
new asn1js.Boolean({
name: (names.critical || ""),
optional: true
}),
new asn1js.OctetString({ name: (names.extnValue || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"extnID",
"critical",
"extnValue"
]);
//endregion
//region Check the schema is valid
let asn1 = asn1js.compareSchema(schema,
schema,
Extension.schema({
names: {
extnID: "extnID",
critical: "critical",
extnValue: "extnValue"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for Extension");
//endregion
//region Get internal properties from parsed schema
this.extnID = asn1.result.extnID.valueBlock.toString();
if("critical" in asn1.result)
this.critical = asn1.result.critical.valueBlock.value;
this.extnValue = asn1.result.extnValue;
//region Get "parsedValue" for well-known extensions
asn1 = asn1js.fromBER(this.extnValue.valueBlock.valueHex);
if(asn1.offset === (-1))
return;
switch(this.extnID)
{
case "2.5.29.9": // SubjectDirectoryAttributes
try
{
this.parsedValue = new SubjectDirectoryAttributes({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new SubjectDirectoryAttributes();
this.parsedValue.parsingError = "Incorrectly formated SubjectDirectoryAttributes";
}
break;
case "2.5.29.14": // SubjectKeyIdentifier
this.parsedValue = asn1.result; // Should be just a simple OCTETSTRING
break;
case "2.5.29.15": // KeyUsage
this.parsedValue = asn1.result; // Should be just a simple BITSTRING
break;
case "2.5.29.16": // PrivateKeyUsagePeriod
try
{
this.parsedValue = new PrivateKeyUsagePeriod({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new PrivateKeyUsagePeriod();
this.parsedValue.parsingError = "Incorrectly formated PrivateKeyUsagePeriod";
}
break;
case "2.5.29.17": // SubjectAltName
case "2.5.29.18": // IssuerAltName
try
{
this.parsedValue = new AltName({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new AltName();
this.parsedValue.parsingError = "Incorrectly formated AltName";
}
break;
case "2.5.29.19": // BasicConstraints
try
{
this.parsedValue = new BasicConstraints({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new BasicConstraints();
this.parsedValue.parsingError = "Incorrectly formated BasicConstraints";
}
break;
case "2.5.29.20": // CRLNumber
case "2.5.29.27": // BaseCRLNumber (delta CRL indicator)
this.parsedValue = asn1.result; // Should be just a simple INTEGER
break;
case "2.5.29.21": // CRLReason
this.parsedValue = asn1.result; // Should be just a simple ENUMERATED
break;
case "2.5.29.24": // InvalidityDate
this.parsedValue = asn1.result; // Should be just a simple GeneralizedTime
break;
case "2.5.29.28": // IssuingDistributionPoint
try
{
this.parsedValue = new IssuingDistributionPoint({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new IssuingDistributionPoint();
this.parsedValue.parsingError = "Incorrectly formated IssuingDistributionPoint";
}
break;
case "2.5.29.29": // CertificateIssuer
try
{
this.parsedValue = new GeneralNames({ schema: asn1.result }); // Should be just a simple
}
catch(ex)
{
this.parsedValue = new GeneralNames();
this.parsedValue.parsingError = "Incorrectly formated GeneralNames";
}
break;
case "2.5.29.30": // NameConstraints
try
{
this.parsedValue = new NameConstraints({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new NameConstraints();
this.parsedValue.parsingError = "Incorrectly formated NameConstraints";
}
break;
case "2.5.29.31": // CRLDistributionPoints
case "2.5.29.46": // FreshestCRL
try
{
this.parsedValue = new CRLDistributionPoints({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new CRLDistributionPoints();
this.parsedValue.parsingError = "Incorrectly formated CRLDistributionPoints";
}
break;
case "2.5.29.32": // CertificatePolicies
case "1.3.6.1.4.1.311.21.10": // szOID_APPLICATION_CERT_POLICIES - Microsoft-specific OID
try
{
this.parsedValue = new CertificatePolicies({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new CertificatePolicies();
this.parsedValue.parsingError = "Incorrectly formated CertificatePolicies";
}
break;
case "2.5.29.33": // PolicyMappings
try
{
this.parsedValue = new PolicyMappings({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new PolicyMappings();
this.parsedValue.parsingError = "Incorrectly formated CertificatePolicies";
}
break;
case "2.5.29.35": // AuthorityKeyIdentifier
try
{
this.parsedValue = new AuthorityKeyIdentifier({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new AuthorityKeyIdentifier();
this.parsedValue.parsingError = "Incorrectly formated AuthorityKeyIdentifier";
}
break;
case "2.5.29.36": // PolicyConstraints
try
{
this.parsedValue = new PolicyConstraints({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new PolicyConstraints();
this.parsedValue.parsingError = "Incorrectly formated PolicyConstraints";
}
break;
case "2.5.29.37": // ExtKeyUsage
try
{
this.parsedValue = new ExtKeyUsage({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new ExtKeyUsage();
this.parsedValue.parsingError = "Incorrectly formated ExtKeyUsage";
}
break;
case "2.5.29.54": // InhibitAnyPolicy
this.parsedValue = asn1.result; // Should be just a simple INTEGER
break;
case "1.3.6.1.5.5.7.1.1": // AuthorityInfoAccess
case "1.3.6.1.5.5.7.1.11": // SubjectInfoAccess
try
{
this.parsedValue = new InfoAccess({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new InfoAccess();
this.parsedValue.parsingError = "Incorrectly formated InfoAccess";
}
break;
case "1.3.6.1.4.1.11129.2.4.2": // SignedCertificateTimestampList
try
{
this.parsedValue = new SignedCertificateTimestampList({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new SignedCertificateTimestampList();
this.parsedValue.parsingError = "Incorrectly formated SignedCertificateTimestampList";
}
break;
case "1.3.6.1.4.1.311.20.2": // szOID_ENROLL_CERTTYPE_EXTENSION - Microsoft-specific extension
this.parsedValue = asn1.result; // Used to be simple Unicode string
break;
case "1.3.6.1.4.1.311.21.2": // szOID_CERTSRV_PREVIOUS_CERT_HASH - Microsoft-specific extension
this.parsedValue = asn1.result; // Used to be simple OctetString
break;
case "1.3.6.1.4.1.311.21.7": // szOID_CERTIFICATE_TEMPLATE - Microsoft-specific extension
try
{
this.parsedValue = new CertificateTemplate({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new CertificateTemplate();
this.parsedValue.parsingError = "Incorrectly formated CertificateTemplate";
}
break;
case "1.3.6.1.4.1.311.21.1": // szOID_CERTSRV_CA_VERSION - Microsoft-specific extension
try
{
this.parsedValue = new CAVersion({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new CAVersion();
this.parsedValue.parsingError = "Incorrectly formated CAVersion";
}
break;
case "1.3.6.1.5.5.7.1.3": // QCStatements
try
{
this.parsedValue = new QCStatements({ schema: asn1.result });
}
catch(ex)
{
this.parsedValue = new QCStatements();
this.parsedValue.parsingError = "Incorrectly formated QCStatements";
}
break;
default:
}
//endregion
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.extnID }));
if(this.critical !== Extension.defaultValues("critical"))
outputArray.push(new asn1js.Boolean({ value: this.critical }));
outputArray.push(this.extnValue);
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
extnID: this.extnID,
extnValue: this.extnValue.toJSON()
};
if(this.critical !== Extension.defaultValues("critical"))
object.critical = this.critical;
if("parsedValue" in this)
{
if("toJSON" in this.parsedValue)
object.parsedValue = this.parsedValue.toJSON();
}
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,137 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import Extension from "./Extension.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class Extensions
{
//**********************************************************************************
/**
* Constructor for Extensions class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<Extension>}
* @desc type
*/
this.extensions = getParametersValue(parameters, "extensions", Extensions.defaultValues("extensions"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "extensions":
return [];
default:
throw new Error(`Invalid member name for Extensions class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
* ```
*
* @param {Object} parameters Input parameters for the schema
* @param {boolean} optional Flag that current schema should be optional
* @returns {Object} asn1js schema object
*/
static schema(parameters = {}, optional = false)
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [extensions]
* @property {string} [extension]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
optional,
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.extensions || ""),
value: Extension.schema(names.extension || {})
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"extensions"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
Extensions.schema({
names: {
extensions: "extensions"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for Extensions");
//endregion
//region Get internal properties from parsed schema
this.extensions = Array.from(asn1.result.extensions, element => new Extension({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.extensions, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
extensions: Array.from(this.extensions, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,644 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
//**************************************************************************************
//region Additional asn1js schema elements existing inside GeneralName schema
//**************************************************************************************
/**
* Schema for "builtInStandardAttributes" of "ORAddress"
* @param {Object} parameters
* @property {Object} [names]
* @param {boolean} optional
* @returns {Sequence}
*/
function builtInStandardAttributes(parameters = {}, optional = false)
{
//builtInStandardAttributes ::= Sequence {
// country-name CountryName OPTIONAL,
// administration-domain-name AdministrationDomainName OPTIONAL,
// network-address [0] IMPLICIT NetworkAddress OPTIONAL,
// terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
// private-domain-name [2] PrivateDomainName OPTIONAL,
// organization-name [3] IMPLICIT OrganizationName OPTIONAL,
// numeric-user-identifier [4] IMPLICIT NumericUserIdentifier OPTIONAL,
// personal-name [5] IMPLICIT PersonalName OPTIONAL,
// organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL }
/**
* @type {Object}
* @property {string} [country_name]
* @property {string} [administration_domain_name]
* @property {string} [network_address]
* @property {string} [terminal_identifier]
* @property {string} [private_domain_name]
* @property {string} [organization_name]
* @property {string} [numeric_user_identifier]
* @property {string} [personal_name]
* @property {string} [organizational_unit_names]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
optional,
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 2, // APPLICATION-SPECIFIC
tagNumber: 1 // [1]
},
name: (names.country_name || ""),
value: [
new asn1js.Choice({
value: [
new asn1js.NumericString(),
new asn1js.PrintableString()
]
})
]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 2, // APPLICATION-SPECIFIC
tagNumber: 2 // [2]
},
name: (names.administration_domain_name || ""),
value: [
new asn1js.Choice({
value: [
new asn1js.NumericString(),
new asn1js.PrintableString()
]
})
]
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
name: (names.network_address || ""),
isHexOnly: true
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
name: (names.terminal_identifier || ""),
isHexOnly: true
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
name: (names.private_domain_name || ""),
value: [
new asn1js.Choice({
value: [
new asn1js.NumericString(),
new asn1js.PrintableString()
]
})
]
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
name: (names.organization_name || ""),
isHexOnly: true
}),
new asn1js.Primitive({
optional: true,
name: (names.numeric_user_identifier || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 4 // [4]
},
isHexOnly: true
}),
new asn1js.Constructed({
optional: true,
name: (names.personal_name || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 5 // [5]
},
value: [
new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
isHexOnly: true
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
isHexOnly: true
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
isHexOnly: true
}),
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
isHexOnly: true
})
]
}),
new asn1js.Constructed({
optional: true,
name: (names.organizational_unit_names || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 6 // [6]
},
value: [
new asn1js.Repeated({
value: new asn1js.PrintableString()
})
]
})
]
}));
}
//**************************************************************************************
/**
* Schema for "builtInDomainDefinedAttributes" of "ORAddress"
* @param {boolean} optional
* @returns {Sequence}
*/
function builtInDomainDefinedAttributes(optional = false)
{
return (new asn1js.Sequence({
optional,
value: [
new asn1js.PrintableString(),
new asn1js.PrintableString()
]
}));
}
//**************************************************************************************
/**
* Schema for "builtInDomainDefinedAttributes" of "ORAddress"
* @param {boolean} optional
* @returns {Set}
*/
function extensionAttributes(optional = false)
{
return (new asn1js.Set({
optional,
value: [
new asn1js.Primitive({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
isHexOnly: true
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [new asn1js.Any()]
})
]
}));
}
//**************************************************************************************
//endregion
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class GeneralName
{
//**********************************************************************************
/**
* Constructor for GeneralName class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
* @property {number} [type] value type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.)
* @property {Object} [value] asn1js object having GeneralName value (type depends on "type" value)
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc value type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.)
*/
this.type = getParametersValue(parameters, "type", GeneralName.defaultValues("type"));
/**
* @type {Object}
* @desc asn1js object having GeneralName value (type depends on "type" value)
*/
this.value = getParametersValue(parameters, "value", GeneralName.defaultValues("value"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "type":
return 9;
case "value":
return {};
default:
throw new Error(`Invalid member name for GeneralName class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "type":
return (memberValue === GeneralName.defaultValues(memberName));
case "value":
return (Object.keys(memberValue).length === 0);
default:
throw new Error(`Invalid member name for GeneralName class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* GeneralName ::= Choice {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] value,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {Object} [directoryName]
* @property {Object} [builtInStandardAttributes]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Choice({
value: [
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier(),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [new asn1js.Any()]
})
]
}),
new asn1js.Primitive({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
}
}),
new asn1js.Primitive({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
}
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
name: (names.blockName || ""),
value: [
builtInStandardAttributes((names.builtInStandardAttributes || {}), false),
builtInDomainDefinedAttributes(true),
extensionAttributes(true)
]
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 4 // [4]
},
name: (names.blockName || ""),
value: [RelativeDistinguishedNames.schema(names.directoryName || {})]
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 5 // [5]
},
name: (names.blockName || ""),
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Choice({
value: [
new asn1js.TeletexString(),
new asn1js.PrintableString(),
new asn1js.UniversalString(),
new asn1js.Utf8String(),
new asn1js.BmpString()
]
})
]
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.Choice({
value: [
new asn1js.TeletexString(),
new asn1js.PrintableString(),
new asn1js.UniversalString(),
new asn1js.Utf8String(),
new asn1js.BmpString()
]
})
]
})
]
}),
new asn1js.Primitive({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 6 // [6]
}
}),
new asn1js.Primitive({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 7 // [7]
}
}),
new asn1js.Primitive({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 8 // [8]
}
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"blockName",
"otherName",
"rfc822Name",
"dNSName",
"x400Address",
"directoryName",
"ediPartyName",
"uniformResourceIdentifier",
"iPAddress",
"registeredID"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
GeneralName.schema({
names: {
blockName: "blockName",
otherName: "otherName",
rfc822Name: "rfc822Name",
dNSName: "dNSName",
x400Address: "x400Address",
directoryName: {
names: {
blockName: "directoryName"
}
},
ediPartyName: "ediPartyName",
uniformResourceIdentifier: "uniformResourceIdentifier",
iPAddress: "iPAddress",
registeredID: "registeredID"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for GeneralName");
//endregion
//region Get internal properties from parsed schema
this.type = asn1.result.blockName.idBlock.tagNumber;
switch(this.type)
{
case 0: // otherName
this.value = asn1.result.blockName;
break;
case 1: // rfc822Name + dNSName + uniformResourceIdentifier
case 2:
case 6:
{
const value = asn1.result.blockName;
value.idBlock.tagClass = 1; // UNIVERSAL
value.idBlock.tagNumber = 22; // IA5STRING
const valueBER = value.toBER(false);
this.value = asn1js.fromBER(valueBER).result.valueBlock.value;
}
break;
case 3: // x400Address
this.value = asn1.result.blockName;
break;
case 4: // directoryName
this.value = new RelativeDistinguishedNames({ schema: asn1.result.directoryName });
break;
case 5: // ediPartyName
this.value = asn1.result.ediPartyName;
break;
case 7: // iPAddress
this.value = new asn1js.OctetString({ valueHex: asn1.result.blockName.valueBlock.valueHex });
break;
case 8: // registeredID
{
const value = asn1.result.blockName;
value.idBlock.tagClass = 1; // UNIVERSAL
value.idBlock.tagNumber = 6; // ObjectIdentifier
const valueBER = value.toBER(false);
this.value = asn1js.fromBER(valueBER).result.valueBlock.toString(); // Getting a string representation of the ObjectIdentifier
}
break;
default:
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
switch(this.type)
{
case 0:
case 3:
case 5:
return new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: this.type
},
value: [
this.value
]
});
case 1:
case 2:
case 6:
{
const value = new asn1js.IA5String({ value: this.value });
value.idBlock.tagClass = 3;
value.idBlock.tagNumber = this.type;
return value;
}
case 4:
return new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 4
},
value: [this.value.toSchema()]
});
case 7:
{
const value = this.value;
value.idBlock.tagClass = 3;
value.idBlock.tagNumber = this.type;
return value;
}
case 8:
{
const value = new asn1js.ObjectIdentifier({ value: this.value });
value.idBlock.tagClass = 3;
value.idBlock.tagNumber = this.type;
return value;
}
default:
return GeneralName.schema();
}
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
type: this.type,
value: ""
};
if((typeof this.value) === "string")
_object.value = this.value;
else
{
try
{
_object.value = this.value.toJSON();
}
catch(ex){}
}
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,138 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class GeneralNames
{
//**********************************************************************************
/**
* Constructor for GeneralNames class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<GeneralName>}
* @desc Array of "general names"
*/
this.names = getParametersValue(parameters, "names", GeneralNames.defaultValues("names"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "names":
return [];
default:
throw new Error(`Invalid member name for GeneralNames class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
* ```
*
* @param {Object} parameters Input parameters for the schema
* @param {boolean} [optional=false] Flag would be element optional or not
* @returns {Object} asn1js schema object
*/
static schema(parameters = {}, optional = false)
{
/**
* @type {Object}
* @property {string} utcTimeName Name for "utcTimeName" choice
* @property {string} generalTimeName Name for "generalTimeName" choice
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
optional,
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.generalNames || ""),
value: GeneralName.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"names",
"generalNames"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
GeneralNames.schema({
names: {
blockName: "names",
generalNames: "generalNames"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for GeneralNames");
//endregion
//region Get internal properties from parsed schema
this.names = Array.from(asn1.result.generalNames, element => new GeneralName({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.names, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
names: Array.from(this.names, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,257 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class GeneralSubtree
{
//**********************************************************************************
/**
* Constructor for GeneralSubtree class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {GeneralName}
* @desc base
*/
this.base = getParametersValue(parameters, "base", GeneralSubtree.defaultValues("base"));
/**
* @type {number|Integer}
* @desc base
*/
this.minimum = getParametersValue(parameters, "minimum", GeneralSubtree.defaultValues("minimum"));
if("maximum" in parameters)
/**
* @type {number|Integer}
* @desc minimum
*/
this.maximum = getParametersValue(parameters, "maximum", GeneralSubtree.defaultValues("maximum"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "base":
return new GeneralName();
case "minimum":
return 0;
case "maximum":
return 0;
default:
throw new Error(`Invalid member name for GeneralSubtree class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* GeneralSubtree ::= SEQUENCE {
* base GeneralName,
* minimum [0] BaseDistance DEFAULT 0,
* maximum [1] BaseDistance OPTIONAL }
*
* BaseDistance ::= INTEGER (0..MAX)
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [base]
* @property {string} [minimum]
* @property {string} [maximum]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
GeneralName.schema(names.base || {}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [new asn1js.Integer({ name: (names.minimum || "") })]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [new asn1js.Integer({ name: (names.maximum || "") })]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"base",
"minimum",
"maximum"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
GeneralSubtree.schema({
names: {
base: {
names: {
blockName: "base"
}
},
minimum: "minimum",
maximum: "maximum"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for GeneralSubtree");
//endregion
//region Get internal properties from parsed schema
this.base = new GeneralName({ schema: asn1.result.base });
if("minimum" in asn1.result)
{
if(asn1.result.minimum.valueBlock.isHexOnly)
this.minimum = asn1.result.minimum;
else
this.minimum = asn1.result.minimum.valueBlock.valueDec;
}
if("maximum" in asn1.result)
{
if(asn1.result.maximum.valueBlock.isHexOnly)
this.maximum = asn1.result.maximum;
else
this.maximum = asn1.result.maximum.valueBlock.valueDec;
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(this.base.toSchema());
if(this.minimum !== 0)
{
let valueMinimum = 0;
if(this.minimum instanceof asn1js.Integer)
valueMinimum = this.minimum;
else
valueMinimum = new asn1js.Integer({ value: this.minimum });
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [valueMinimum]
}));
}
if("maximum" in this)
{
let valueMaximum = 0;
if(this.maximum instanceof asn1js.Integer)
valueMaximum = this.maximum;
else
valueMaximum = new asn1js.Integer({ value: this.maximum });
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [valueMaximum]
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
base: this.base.toJSON()
};
if(this.minimum !== 0)
{
if((typeof this.minimum) === "number")
object.minimum = this.minimum;
else
object.minimum = this.minimum.toJSON();
}
if("maximum" in this)
{
if((typeof this.maximum) === "number")
object.maximum = this.maximum;
else
object.maximum = this.maximum.toJSON();
}
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,135 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AccessDescription from "./AccessDescription.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class InfoAccess
{
//**********************************************************************************
/**
* Constructor for InfoAccess class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Array.<AccessDescription>}
* @desc accessDescriptions
*/
this.accessDescriptions = getParametersValue(parameters, "accessDescriptions", InfoAccess.defaultValues("accessDescriptions"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "accessDescriptions":
return [];
default:
throw new Error(`Invalid member name for InfoAccess class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* AuthorityInfoAccessSyntax ::=
* SEQUENCE SIZE (1..MAX) OF AccessDescription
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [accessDescriptions]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Repeated({
name: (names.accessDescriptions || ""),
value: AccessDescription.schema()
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"accessDescriptions"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
InfoAccess.schema({
names: {
accessDescriptions: "accessDescriptions"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for InfoAccess");
//endregion
//region Get internal properties from parsed schema
this.accessDescriptions = Array.from(asn1.result.accessDescriptions, element => new AccessDescription({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: Array.from(this.accessDescriptions, element => element.toSchema())
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
accessDescriptions: Array.from(this.accessDescriptions, element => element.toJSON())
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,155 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class IssuerAndSerialNumber
{
//**********************************************************************************
/**
* Constructor for IssuerAndSerialNumber class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {RelativeDistinguishedNames}
* @desc issuer
*/
this.issuer = getParametersValue(parameters, "issuer", IssuerAndSerialNumber.defaultValues("issuer"));
/**
* @type {Integer}
* @desc serialNumber
*/
this.serialNumber = getParametersValue(parameters, "serialNumber", IssuerAndSerialNumber.defaultValues("serialNumber"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "issuer":
return new RelativeDistinguishedNames();
case "serialNumber":
return new asn1js.Integer();
default:
throw new Error(`Invalid member name for IssuerAndSerialNumber class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* IssuerAndSerialNumber ::= SEQUENCE {
* issuer Name,
* serialNumber CertificateSerialNumber }
*
* CertificateSerialNumber ::= INTEGER
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [issuer]
* @property {string} [serialNumber]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
RelativeDistinguishedNames.schema(names.issuer || {}),
new asn1js.Integer({ name: (names.serialNumber || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"issuer",
"serialNumber"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
IssuerAndSerialNumber.schema({
names: {
issuer: {
names: {
blockName: "issuer"
}
},
serialNumber: "serialNumber"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for IssuerAndSerialNumber");
//endregion
//region Get internal properties from parsed schema
this.issuer = new RelativeDistinguishedNames({ schema: asn1.result.issuer });
this.serialNumber = asn1.result.serialNumber;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
this.issuer.toSchema(),
this.serialNumber
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
issuer: this.issuer.toJSON(),
serialNumber: this.serialNumber.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,449 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralName from "./GeneralName.js";
import RelativeDistinguishedNames from "./RelativeDistinguishedNames.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class IssuingDistributionPoint
{
//**********************************************************************************
/**
* Constructor for IssuingDistributionPoint class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("distributionPoint" in parameters)
/**
* @type {Array.<GeneralName>|RelativeDistinguishedNames}
* @desc distributionPoint
*/
this.distributionPoint = getParametersValue(parameters, "distributionPoint", IssuingDistributionPoint.defaultValues("distributionPoint"));
/**
* @type {boolean}
* @desc onlyContainsUserCerts
*/
this.onlyContainsUserCerts = getParametersValue(parameters, "onlyContainsUserCerts", IssuingDistributionPoint.defaultValues("onlyContainsUserCerts"));
/**
* @type {boolean}
* @desc onlyContainsCACerts
*/
this.onlyContainsCACerts = getParametersValue(parameters, "onlyContainsCACerts", IssuingDistributionPoint.defaultValues("onlyContainsCACerts"));
if("onlySomeReasons" in parameters)
/**
* @type {number}
* @desc onlySomeReasons
*/
this.onlySomeReasons = getParametersValue(parameters, "onlySomeReasons", IssuingDistributionPoint.defaultValues("onlySomeReasons"));
/**
* @type {boolean}
* @desc indirectCRL
*/
this.indirectCRL = getParametersValue(parameters, "indirectCRL", IssuingDistributionPoint.defaultValues("indirectCRL"));
/**
* @type {boolean}
* @desc onlyContainsAttributeCerts
*/
this.onlyContainsAttributeCerts = getParametersValue(parameters, "onlyContainsAttributeCerts", IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "distributionPoint":
return [];
case "onlyContainsUserCerts":
return false;
case "onlyContainsCACerts":
return false;
case "onlySomeReasons":
return 0;
case "indirectCRL":
return false;
case "onlyContainsAttributeCerts":
return false;
default:
throw new Error(`Invalid member name for IssuingDistributionPoint class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* IssuingDistributionPoint ::= SEQUENCE {
* distributionPoint [0] DistributionPointName OPTIONAL,
* onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
* onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
* onlySomeReasons [3] ReasonFlags OPTIONAL,
* indirectCRL [4] BOOLEAN DEFAULT FALSE,
* onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
*
* ReasonFlags ::= BIT STRING {
* unused (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6),
* privilegeWithdrawn (7),
* aACompromise (8) }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [distributionPoint]
* @property {string} [distributionPointNames]
* @property {string} [onlyContainsUserCerts]
* @property {string} [onlyContainsCACerts]
* @property {string} [onlySomeReasons]
* @property {string} [indirectCRL]
* @property {string} [onlyContainsAttributeCerts]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Choice({
value: [
new asn1js.Constructed({
name: (names.distributionPoint || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Repeated({
name: (names.distributionPointNames || ""),
value: GeneralName.schema()
})
]
}),
new asn1js.Constructed({
name: (names.distributionPoint || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: RelativeDistinguishedNames.schema().valueBlock.value
})
]
})
]
}),
new asn1js.Primitive({
name: (names.onlyContainsUserCerts || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
}
}), // IMPLICIT boolean value
new asn1js.Primitive({
name: (names.onlyContainsCACerts || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
}
}), // IMPLICIT boolean value
new asn1js.Primitive({
name: (names.onlySomeReasons || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
}
}), // IMPLICIT bitstring value
new asn1js.Primitive({
name: (names.indirectCRL || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 4 // [4]
}
}), // IMPLICIT boolean value
new asn1js.Primitive({
name: (names.onlyContainsAttributeCerts || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 5 // [5]
}
}) // IMPLICIT boolean value
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"distributionPoint",
"distributionPointNames",
"onlyContainsUserCerts",
"onlyContainsCACerts",
"onlySomeReasons",
"indirectCRL",
"onlyContainsAttributeCerts"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
IssuingDistributionPoint.schema({
names: {
distributionPoint: "distributionPoint",
distributionPointNames: "distributionPointNames",
onlyContainsUserCerts: "onlyContainsUserCerts",
onlyContainsCACerts: "onlyContainsCACerts",
onlySomeReasons: "onlySomeReasons",
indirectCRL: "indirectCRL",
onlyContainsAttributeCerts: "onlyContainsAttributeCerts"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for IssuingDistributionPoint");
//endregion
//region Get internal properties from parsed schema
if("distributionPoint" in asn1.result)
{
switch(true)
{
case (asn1.result.distributionPoint.idBlock.tagNumber === 0): // GENERAL_NAMES variant
this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new GeneralName({ schema: element }));
break;
case (asn1.result.distributionPoint.idBlock.tagNumber === 1): // RDN variant
{
this.distributionPoint = new RelativeDistinguishedNames({
schema: new asn1js.Sequence({
value: asn1.result.distributionPoint.valueBlock.value
})
});
}
break;
default:
throw new Error("Unknown tagNumber for distributionPoint: {$asn1.result.distributionPoint.idBlock.tagNumber}");
}
}
if("onlyContainsUserCerts" in asn1.result)
{
const view = new Uint8Array(asn1.result.onlyContainsUserCerts.valueBlock.valueHex);
this.onlyContainsUserCerts = (view[0] !== 0x00);
}
if("onlyContainsCACerts" in asn1.result)
{
const view = new Uint8Array(asn1.result.onlyContainsCACerts.valueBlock.valueHex);
this.onlyContainsCACerts = (view[0] !== 0x00);
}
if("onlySomeReasons" in asn1.result)
{
const view = new Uint8Array(asn1.result.onlySomeReasons.valueBlock.valueHex);
this.onlySomeReasons = view[0];
}
if("indirectCRL" in asn1.result)
{
const view = new Uint8Array(asn1.result.indirectCRL.valueBlock.valueHex);
this.indirectCRL = (view[0] !== 0x00);
}
if("onlyContainsAttributeCerts" in asn1.result)
{
const view = new Uint8Array(asn1.result.onlyContainsAttributeCerts.valueBlock.valueHex);
this.onlyContainsAttributeCerts = (view[0] !== 0x00);
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if("distributionPoint" in this)
{
let value;
if(this.distributionPoint instanceof Array)
{
value = new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: Array.from(this.distributionPoint, element => element.toSchema())
});
}
else
{
value = this.distributionPoint.toSchema();
value.idBlock.tagClass = 3; // CONTEXT - SPECIFIC
value.idBlock.tagNumber = 1; // [1]
}
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [value]
}));
}
if(this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues("onlyContainsUserCerts"))
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
valueHex: (new Uint8Array([0xFF])).buffer
}));
}
if(this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues("onlyContainsCACerts"))
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 2 // [2]
},
valueHex: (new Uint8Array([0xFF])).buffer
}));
}
if("onlySomeReasons" in this)
{
const buffer = new ArrayBuffer(1);
const view = new Uint8Array(buffer);
view[0] = this.onlySomeReasons;
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 3 // [3]
},
valueHex: buffer
}));
}
if(this.indirectCRL !== IssuingDistributionPoint.defaultValues("indirectCRL"))
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 4 // [4]
},
valueHex: (new Uint8Array([0xFF])).buffer
}));
}
if(this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts"))
{
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 5 // [5]
},
valueHex: (new Uint8Array([0xFF])).buffer
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if("distributionPoint" in this)
{
if(this.distributionPoint instanceof Array)
object.distributionPoint = Array.from(this.distributionPoint, element => element.toJSON());
else
object.distributionPoint = this.distributionPoint.toJSON();
}
if(this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues("onlyContainsUserCerts"))
object.onlyContainsUserCerts = this.onlyContainsUserCerts;
if(this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues("onlyContainsCACerts"))
object.onlyContainsCACerts = this.onlyContainsCACerts;
if("onlySomeReasons" in this)
object.onlySomeReasons = this.onlySomeReasons;
if(this.indirectCRL !== IssuingDistributionPoint.defaultValues("indirectCRL"))
object.indirectCRL = this.indirectCRL;
if(this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues("onlyContainsAttributeCerts"))
object.onlyContainsAttributeCerts = this.onlyContainsAttributeCerts;
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,220 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import OtherKeyAttribute from "./OtherKeyAttribute.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class KEKIdentifier
{
//**********************************************************************************
/**
* Constructor for KEKIdentifier class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {OctetString}
* @desc keyIdentifier
*/
this.keyIdentifier = getParametersValue(parameters, "keyIdentifier", KEKIdentifier.defaultValues("keyIdentifier"));
if("date" in parameters)
/**
* @type {GeneralizedTime}
* @desc date
*/
this.date = getParametersValue(parameters, "date", KEKIdentifier.defaultValues("date"));
if("other" in parameters)
/**
* @type {OtherKeyAttribute}
* @desc other
*/
this.other = getParametersValue(parameters, "other", KEKIdentifier.defaultValues("other"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "keyIdentifier":
return new asn1js.OctetString();
case "date":
return new asn1js.GeneralizedTime();
case "other":
return new OtherKeyAttribute();
default:
throw new Error(`Invalid member name for KEKIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "keyIdentifier":
return (memberValue.isEqual(KEKIdentifier.defaultValues("keyIdentifier")));
case "date":
// noinspection OverlyComplexBooleanExpressionJS
return ((memberValue.year === 0) &&
(memberValue.month === 0) &&
(memberValue.day === 0) &&
(memberValue.hour === 0) &&
(memberValue.minute === 0) &&
(memberValue.second === 0) &&
(memberValue.millisecond === 0));
case "other":
return ((memberValue.compareWithDefault("keyAttrId", memberValue.keyAttrId)) &&
(("keyAttr" in memberValue) === false));
default:
throw new Error(`Invalid member name for KEKIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* KEKIdentifier ::= SEQUENCE {
* keyIdentifier OCTET STRING,
* date GeneralizedTime OPTIONAL,
* other OtherKeyAttribute OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [keyIdentifier]
* @property {string} [date]
* @property {string} [other]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.OctetString({ name: (names.keyIdentifier || "") }),
new asn1js.GeneralizedTime({
optional: true,
name: (names.date || "")
}),
OtherKeyAttribute.schema(names.other || {})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"keyIdentifier",
"date",
"other"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
KEKIdentifier.schema({
names: {
keyIdentifier: "keyIdentifier",
date: "date",
other: {
names: {
blockName: "other"
}
}
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for KEKIdentifier");
//endregion
//region Get internal properties from parsed schema
this.keyIdentifier = asn1.result.keyIdentifier;
if("date" in asn1.result)
this.date = asn1.result.date;
if("other" in asn1.result)
this.other = new OtherKeyAttribute({ schema: asn1.result.other });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(this.keyIdentifier);
if("date" in this)
outputArray.push(this.date);
if("other" in this)
outputArray.push(this.other.toSchema());
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
keyIdentifier: this.keyIdentifier.toJSON()
};
if("date" in this)
_object.date = this.date;
if("other" in this)
_object.other = this.other.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,221 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import KEKIdentifier from "./KEKIdentifier.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class KEKRecipientInfo
{
//**********************************************************************************
/**
* Constructor for KEKRecipientInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", KEKRecipientInfo.defaultValues("version"));
/**
* @type {KEKIdentifier}
* @desc kekid
*/
this.kekid = getParametersValue(parameters, "kekid", KEKRecipientInfo.defaultValues("kekid"));
/**
* @type {AlgorithmIdentifier}
* @desc keyEncryptionAlgorithm
*/
this.keyEncryptionAlgorithm = getParametersValue(parameters, "keyEncryptionAlgorithm", KEKRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
/**
* @type {OctetString}
* @desc encryptedKey
*/
this.encryptedKey = getParametersValue(parameters, "encryptedKey", KEKRecipientInfo.defaultValues("encryptedKey"));
/**
* @type {ArrayBuffer}
* @desc preDefinedKEK KEK using to encrypt CEK
*/
this.preDefinedKEK = getParametersValue(parameters, "preDefinedKEK", KEKRecipientInfo.defaultValues("preDefinedKEK"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return 0;
case "kekid":
return new KEKIdentifier();
case "keyEncryptionAlgorithm":
return new AlgorithmIdentifier();
case "encryptedKey":
return new asn1js.OctetString();
case "preDefinedKEK":
return new ArrayBuffer(0);
default:
throw new Error(`Invalid member name for KEKRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "KEKRecipientInfo":
return (memberValue === KEKRecipientInfo.defaultValues("version"));
case "kekid":
return ((memberValue.compareWithDefault("keyIdentifier", memberValue.keyIdentifier)) &&
(("date" in memberValue) === false) &&
(("other" in memberValue) === false));
case "keyEncryptionAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "encryptedKey":
return (memberValue.isEqual(KEKRecipientInfo.defaultValues("encryptedKey")));
case "preDefinedKEK":
return (memberValue.byteLength === 0);
default:
throw new Error(`Invalid member name for KEKRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* KEKRecipientInfo ::= SEQUENCE {
* version CMSVersion, -- always set to 4
* kekid KEKIdentifier,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* encryptedKey EncryptedKey }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [version]
* @property {string} [kekid]
* @property {string} [keyEncryptionAlgorithm]
* @property {string} [encryptedKey]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Integer({ name: (names.version || "") }),
KEKIdentifier.schema(names.kekid || {}),
AlgorithmIdentifier.schema(names.keyEncryptionAlgorithm || {}),
new asn1js.OctetString({ name: (names.encryptedKey || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"kekid",
"keyEncryptionAlgorithm",
"encryptedKey"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
KEKRecipientInfo.schema({
names: {
version: "version",
kekid: {
names: {
blockName: "kekid"
}
},
keyEncryptionAlgorithm: {
names: {
blockName: "keyEncryptionAlgorithm"
}
},
encryptedKey: "encryptedKey"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for KEKRecipientInfo");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
this.kekid = new KEKIdentifier({ schema: asn1.result.kekid });
this.keyEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.keyEncryptionAlgorithm });
this.encryptedKey = asn1.result.encryptedKey;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.Integer({ value: this.version }),
this.kekid.toSchema(),
this.keyEncryptionAlgorithm.toSchema(),
this.encryptedKey
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
version: this.version,
kekid: this.kekid.toJSON(),
keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(),
encryptedKey: this.encryptedKey.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,206 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import IssuerAndSerialNumber from "./IssuerAndSerialNumber.js";
import RecipientKeyIdentifier from "./RecipientKeyIdentifier.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class KeyAgreeRecipientIdentifier
{
//**********************************************************************************
/**
* Constructor for KeyAgreeRecipientIdentifier class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc variant
*/
this.variant = getParametersValue(parameters, "variant", KeyAgreeRecipientIdentifier.defaultValues("variant"));
/**
* @type {*}
* @desc values
*/
this.value = getParametersValue(parameters, "value", KeyAgreeRecipientIdentifier.defaultValues("value"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "variant":
return (-1);
case "value":
return {};
default:
throw new Error(`Invalid member name for KeyAgreeRecipientIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "variant":
return (memberValue === (-1));
case "value":
return (Object.keys(memberValue).length === 0);
default:
throw new Error(`Invalid member name for KeyAgreeRecipientIdentifier class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* KeyAgreeRecipientIdentifier ::= CHOICE {
* issuerAndSerialNumber IssuerAndSerialNumber,
* rKeyId [0] IMPLICIT RecipientKeyIdentifier }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [issuerAndSerialNumber]
* @property {string} [rKeyId]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Choice({
value: [
IssuerAndSerialNumber.schema(names.issuerAndSerialNumber || {
names: {
blockName: (names.blockName || "")
}
}),
new asn1js.Constructed({
name: (names.blockName || ""),
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: RecipientKeyIdentifier.schema(names.rKeyId || {
names: {
blockName: (names.blockName || "")
}
}).valueBlock.value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"blockName"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
KeyAgreeRecipientIdentifier.schema({
names: {
blockName: "blockName"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientIdentifier");
//endregion
//region Get internal properties from parsed schema
if(asn1.result.blockName.idBlock.tagClass === 1)
{
this.variant = 1;
this.value = new IssuerAndSerialNumber({ schema: asn1.result.blockName });
}
else
{
this.variant = 2;
this.value = new RecipientKeyIdentifier({
schema: new asn1js.Sequence({
value: asn1.result.blockName.valueBlock.value
})
});
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
switch(this.variant)
{
case 1:
return this.value.toSchema();
case 2:
return new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: this.value.toSchema().valueBlock.value
});
default:
return new asn1js.Any();
}
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
variant: this.variant
};
if((this.variant === 1) || (this.variant === 2))
_object.value = this.value.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,290 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import OriginatorIdentifierOrKey from "./OriginatorIdentifierOrKey.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import RecipientEncryptedKeys from "./RecipientEncryptedKeys.js";
import Certificate from "./Certificate.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class KeyAgreeRecipientInfo
{
//**********************************************************************************
/**
* Constructor for KeyAgreeRecipientInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", KeyAgreeRecipientInfo.defaultValues("version"));
/**
* @type {OriginatorIdentifierOrKey}
* @desc originator
*/
this.originator = getParametersValue(parameters, "originator", KeyAgreeRecipientInfo.defaultValues("originator"));
if("ukm" in parameters)
/**
* @type {OctetString}
* @desc ukm
*/
this.ukm = getParametersValue(parameters, "ukm", KeyAgreeRecipientInfo.defaultValues("ukm"));
/**
* @type {AlgorithmIdentifier}
* @desc keyEncryptionAlgorithm
*/
this.keyEncryptionAlgorithm = getParametersValue(parameters, "keyEncryptionAlgorithm", KeyAgreeRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
/**
* @type {RecipientEncryptedKeys}
* @desc recipientEncryptedKeys
*/
this.recipientEncryptedKeys = getParametersValue(parameters, "recipientEncryptedKeys", KeyAgreeRecipientInfo.defaultValues("recipientEncryptedKeys"));
/**
* @type {Certificate}
* @desc recipientCertificate For some reasons we need to store recipient's certificate here
*/
this.recipientCertificate = getParametersValue(parameters, "recipientCertificate", KeyAgreeRecipientInfo.defaultValues("recipientCertificate"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return 0;
case "originator":
return new OriginatorIdentifierOrKey();
case "ukm":
return new asn1js.OctetString();
case "keyEncryptionAlgorithm":
return new AlgorithmIdentifier();
case "recipientEncryptedKeys":
return new RecipientEncryptedKeys();
case "recipientCertificate":
return new Certificate();
default:
throw new Error(`Invalid member name for KeyAgreeRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "version":
return (memberValue === 0);
case "originator":
return ((memberValue.variant === (-1)) && (("value" in memberValue) === false));
case "ukm":
return (memberValue.isEqual(KeyAgreeRecipientInfo.defaultValues("ukm")));
case "keyEncryptionAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "recipientEncryptedKeys":
return (memberValue.encryptedKeys.length === 0);
case "recipientCertificate":
return false; // For now leave it as is
default:
throw new Error(`Invalid member name for KeyAgreeRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* KeyAgreeRecipientInfo ::= SEQUENCE {
* version CMSVersion, -- always set to 3
* originator [0] EXPLICIT OriginatorIdentifierOrKey,
* ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* recipientEncryptedKeys RecipientEncryptedKeys }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [version]
* @property {string} [originator]
* @property {string} [ukm]
* @property {string} [keyEncryptionAlgorithm]
* @property {string} [recipientEncryptedKeys]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: names.blockName || "",
value: [
new asn1js.Integer({ name: names.version || "" }),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
OriginatorIdentifierOrKey.schema(names.originator || {})
]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [new asn1js.OctetString({ name: names.ukm || "" })]
}),
AlgorithmIdentifier.schema(names.keyEncryptionAlgorithm || {}),
RecipientEncryptedKeys.schema(names.recipientEncryptedKeys || {})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"originator",
"ukm",
"keyEncryptionAlgorithm",
"recipientEncryptedKeys"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
KeyAgreeRecipientInfo.schema({
names: {
version: "version",
originator: {
names: {
blockName: "originator"
}
},
ukm: "ukm",
keyEncryptionAlgorithm: {
names: {
blockName: "keyEncryptionAlgorithm"
}
},
recipientEncryptedKeys: {
names: {
blockName: "recipientEncryptedKeys"
}
}
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientInfo");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
this.originator = new OriginatorIdentifierOrKey({ schema: asn1.result.originator });
if("ukm" in asn1.result)
this.ukm = asn1.result.ukm;
this.keyEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.keyEncryptionAlgorithm });
this.recipientEncryptedKeys = new RecipientEncryptedKeys({ schema: asn1.result.recipientEncryptedKeys });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for final sequence
const outputArray = [];
outputArray.push(new asn1js.Integer({ value: this.version }));
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.originator.toSchema()]
}));
if("ukm" in this)
{
outputArray.push(new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [this.ukm]
}));
}
outputArray.push(this.keyEncryptionAlgorithm.toSchema());
outputArray.push(this.recipientEncryptedKeys.toSchema());
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
version: this.version,
originator: this.originator.toJSON()
};
if("ukm" in this)
_object.ukm = this.ukm.toJSON();
_object.keyEncryptionAlgorithm = this.keyEncryptionAlgorithm.toJSON();
_object.recipientEncryptedKeys = this.recipientEncryptedKeys.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,20 +0,0 @@
import PrivateKeyInfo from "./PrivateKeyInfo.js";
//**************************************************************************************
/**
* Class from RFC5208
*/
export default class KeyBag extends PrivateKeyInfo
{
//**********************************************************************************
/**
* Constructor for Attribute class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
super(parameters);
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,248 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
import Certificate from "./Certificate.js";
import RecipientIdentifier from "./RecipientIdentifier.js";
import IssuerAndSerialNumber from "./IssuerAndSerialNumber.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class KeyTransRecipientInfo
{
//**********************************************************************************
/**
* Constructor for KeyTransRecipientInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc version
*/
this.version = getParametersValue(parameters, "version", KeyTransRecipientInfo.defaultValues("version"));
/**
* @type {RecipientIdentifier}
* @desc rid
*/
this.rid = getParametersValue(parameters, "rid", KeyTransRecipientInfo.defaultValues("rid"));
/**
* @type {AlgorithmIdentifier}
* @desc keyEncryptionAlgorithm
*/
this.keyEncryptionAlgorithm = getParametersValue(parameters, "keyEncryptionAlgorithm", KeyTransRecipientInfo.defaultValues("keyEncryptionAlgorithm"));
/**
* @type {OctetString}
* @desc encryptedKey
*/
this.encryptedKey = getParametersValue(parameters, "encryptedKey", KeyTransRecipientInfo.defaultValues("encryptedKey"));
/**
* @type {Certificate}
* @desc recipientCertificate For some reasons we need to store recipient's certificate here
*/
this.recipientCertificate = getParametersValue(parameters, "recipientCertificate", KeyTransRecipientInfo.defaultValues("recipientCertificate"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "version":
return (-1);
case "rid":
return {};
case "keyEncryptionAlgorithm":
return new AlgorithmIdentifier();
case "encryptedKey":
return new asn1js.OctetString();
case "recipientCertificate":
return new Certificate();
default:
throw new Error(`Invalid member name for KeyTransRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "version":
return (memberValue === KeyTransRecipientInfo.defaultValues("version"));
case "rid":
return (Object.keys(memberValue).length === 0);
case "keyEncryptionAlgorithm":
case "encryptedKey":
return memberValue.isEqual(KeyTransRecipientInfo.defaultValues(memberName));
case "recipientCertificate":
return false; // For now we do not need to compare any values with the "recipientCertificate"
default:
throw new Error(`Invalid member name for KeyTransRecipientInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* KeyTransRecipientInfo ::= SEQUENCE {
* version CMSVersion, -- always set to 0 or 2
* rid RecipientIdentifier,
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
* encryptedKey EncryptedKey }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [version]
* @property {string} [rid]
* @property {string} [keyEncryptionAlgorithm]
* @property {string} [encryptedKey]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Integer({ name: (names.version || "") }),
RecipientIdentifier.schema(names.rid || {}),
AlgorithmIdentifier.schema(names.keyEncryptionAlgorithm || {}),
new asn1js.OctetString({ name: (names.encryptedKey || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"version",
"rid",
"keyEncryptionAlgorithm",
"encryptedKey"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
KeyTransRecipientInfo.schema({
names: {
version: "version",
rid: {
names: {
blockName: "rid"
}
},
keyEncryptionAlgorithm: {
names: {
blockName: "keyEncryptionAlgorithm"
}
},
encryptedKey: "encryptedKey"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for KeyTransRecipientInfo");
//endregion
//region Get internal properties from parsed schema
this.version = asn1.result.version.valueBlock.valueDec;
if(asn1.result.rid.idBlock.tagClass === 3)
this.rid = new asn1js.OctetString({ valueHex: asn1.result.rid.valueBlock.valueHex }); // SubjectKeyIdentifier
else
this.rid = new IssuerAndSerialNumber({ schema: asn1.result.rid });
this.keyEncryptionAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.keyEncryptionAlgorithm });
this.encryptedKey = asn1.result.encryptedKey;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if(this.rid instanceof IssuerAndSerialNumber)
{
this.version = 0;
outputArray.push(new asn1js.Integer({ value: this.version }));
outputArray.push(this.rid.toSchema());
}
else
{
this.version = 2;
outputArray.push(new asn1js.Integer({ value: this.version }));
outputArray.push(new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
valueHex: this.rid.valueBlock.valueHex
}));
}
outputArray.push(this.keyEncryptionAlgorithm.toSchema());
outputArray.push(this.encryptedKey);
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
version: this.version,
rid: this.rid.toJSON(),
keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(),
encryptedKey: this.encryptedKey.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,214 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import DigestInfo from "./DigestInfo.js";
//**************************************************************************************
/**
* Class from RFC7292
*/
export default class MacData
{
//**********************************************************************************
/**
* Constructor for MacData class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {DigestInfo}
* @desc mac
*/
this.mac = getParametersValue(parameters, "mac", MacData.defaultValues("mac"));
/**
* @type {OctetString}
* @desc macSalt
*/
this.macSalt = getParametersValue(parameters, "macSalt", MacData.defaultValues("macSalt"));
if("iterations" in parameters)
/**
* @type {number}
* @desc iterations
*/
this.iterations = getParametersValue(parameters, "iterations", MacData.defaultValues("iterations"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "mac":
return new DigestInfo();
case "macSalt":
return new asn1js.OctetString();
case "iterations":
return 1;
default:
throw new Error(`Invalid member name for MacData class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "mac":
return ((DigestInfo.compareWithDefault("digestAlgorithm", memberValue.digestAlgorithm)) &&
(DigestInfo.compareWithDefault("digest", memberValue.digest)));
case "macSalt":
return (memberValue.isEqual(MacData.defaultValues(memberName)));
case "iterations":
return (memberValue === MacData.defaultValues(memberName));
default:
throw new Error(`Invalid member name for MacData class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* MacData ::= SEQUENCE {
* mac DigestInfo,
* macSalt OCTET STRING,
* iterations INTEGER DEFAULT 1
* -- Note: The default is for historical reasons and its use is
* -- deprecated. A higher value, like 1024 is recommended.
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [optional]
* @property {string} [mac]
* @property {string} [macSalt]
* @property {string} [iterations]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
optional: (names.optional || true),
value: [
DigestInfo.schema(names.mac || {
names: {
blockName: "mac"
}
}),
new asn1js.OctetString({ name: (names.macSalt || "macSalt") }),
new asn1js.Integer({
optional: true,
name: (names.iterations || "iterations")
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"mac",
"macSalt",
"iterations"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
MacData.schema({
names: {
mac: {
names: {
blockName: "mac"
}
},
macSalt: "macSalt",
iterations: "iterations"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for MacData");
//endregion
//region Get internal properties from parsed schema
this.mac = new DigestInfo({ schema: asn1.result.mac });
this.macSalt = asn1.result.macSalt;
if("iterations" in asn1.result)
this.iterations = asn1.result.iterations.valueBlock.valueDec;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
const outputArray = [
this.mac.toSchema(),
this.macSalt
];
if("iterations" in this)
outputArray.push(new asn1js.Integer({ value: this.iterations }));
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const output = {
mac: this.mac.toJSON(),
macSalt: this.macSalt.toJSON()
};
if("iterations" in this)
output.iterations = this.iterations.toJSON();
return output;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,171 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC3161
*/
export default class MessageImprint
{
//**********************************************************************************
/**
* Constructor for MessageImprint class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AlgorithmIdentifier}
* @desc hashAlgorithm
*/
this.hashAlgorithm = getParametersValue(parameters, "hashAlgorithm", MessageImprint.defaultValues("hashAlgorithm"));
/**
* @type {OctetString}
* @desc hashedMessage
*/
this.hashedMessage = getParametersValue(parameters, "hashedMessage", MessageImprint.defaultValues("hashedMessage"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "hashAlgorithm":
return new AlgorithmIdentifier();
case "hashedMessage":
return new asn1js.OctetString();
default:
throw new Error(`Invalid member name for MessageImprint class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "hashAlgorithm":
return ((memberValue.algorithmId === "") && (("algorithmParams" in memberValue) === false));
case "hashedMessage":
return (memberValue.isEqual(MessageImprint.defaultValues(memberName)) === 0);
default:
throw new Error(`Invalid member name for MessageImprint class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* MessageImprint ::= SEQUENCE {
* hashAlgorithm AlgorithmIdentifier,
* hashedMessage OCTET STRING }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [hashAlgorithm]
* @property {string} [hashedMessage]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AlgorithmIdentifier.schema(names.hashAlgorithm || {}),
new asn1js.OctetString({ name: (names.hashedMessage || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"hashAlgorithm",
"hashedMessage"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
MessageImprint.schema({
names: {
hashAlgorithm: {
names: {
blockName: "hashAlgorithm"
}
},
hashedMessage: "hashedMessage"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for MessageImprint");
//endregion
//region Get internal properties from parsed schema
this.hashAlgorithm = new AlgorithmIdentifier({ schema: asn1.result.hashAlgorithm });
this.hashedMessage = asn1.result.hashedMessage;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
this.hashAlgorithm.toSchema(),
this.hashedMessage
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
hashAlgorithm: this.hashAlgorithm.toJSON(),
hashedMessage: this.hashedMessage.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,207 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import GeneralSubtree from "./GeneralSubtree.js";
//**************************************************************************************
/**
* Class from RFC5280
*/
export default class NameConstraints
{
//**********************************************************************************
/**
* Constructor for NameConstraints class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("permittedSubtrees" in parameters)
/**
* @type {Array.<GeneralSubtree>}
* @desc permittedSubtrees
*/
this.permittedSubtrees = getParametersValue(parameters, "permittedSubtrees", NameConstraints.defaultValues("permittedSubtrees"));
if("excludedSubtrees" in parameters)
/**
* @type {Array.<GeneralSubtree>}
* @desc excludedSubtrees
*/
this.excludedSubtrees = getParametersValue(parameters, "excludedSubtrees", NameConstraints.defaultValues("excludedSubtrees"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "permittedSubtrees":
return [];
case "excludedSubtrees":
return [];
default:
throw new Error(`Invalid member name for NameConstraints class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* NameConstraints ::= SEQUENCE {
* permittedSubtrees [0] GeneralSubtrees OPTIONAL,
* excludedSubtrees [1] GeneralSubtrees OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [permittedSubtrees]
* @property {string} [excludedSubtrees]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
new asn1js.Repeated({
name: (names.permittedSubtrees || ""),
value: GeneralSubtree.schema()
})
]
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: [
new asn1js.Repeated({
name: (names.excludedSubtrees || ""),
value: GeneralSubtree.schema()
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"permittedSubtrees",
"excludedSubtrees"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
NameConstraints.schema({
names: {
permittedSubtrees: "permittedSubtrees",
excludedSubtrees: "excludedSubtrees"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for NameConstraints");
//endregion
//region Get internal properties from parsed schema
if("permittedSubtrees" in asn1.result)
this.permittedSubtrees = Array.from(asn1.result.permittedSubtrees, element => new GeneralSubtree({ schema: element }));
if("excludedSubtrees" in asn1.result)
this.excludedSubtrees = Array.from(asn1.result.excludedSubtrees, element => new GeneralSubtree({ schema: element }));
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
if("permittedSubtrees" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: Array.from(this.permittedSubtrees, element => element.toSchema())
}));
}
if("excludedSubtrees" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: Array.from(this.excludedSubtrees, element => element.toSchema())
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if("permittedSubtrees" in this)
object.permittedSubtrees = Array.from(this.permittedSubtrees, element => element.toJSON());
if("excludedSubtrees" in this)
object.excludedSubtrees = Array.from(this.excludedSubtrees, element => element.toJSON());
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,304 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import { getEngine } from "./common.js";
import TBSRequest from "./TBSRequest.js";
import Signature from "./Signature.js";
import Request from "./Request.js";
import CertID from "./CertID.js";
//**************************************************************************************
/**
* Class from RFC6960
*/
export default class OCSPRequest
{
//**********************************************************************************
/**
* Constructor for OCSPRequest class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {TBSRequest}
* @desc tbsRequest
*/
this.tbsRequest = getParametersValue(parameters, "tbsRequest", OCSPRequest.defaultValues("tbsRequest"));
if("optionalSignature" in parameters)
/**
* @type {Signature}
* @desc optionalSignature
*/
this.optionalSignature = getParametersValue(parameters, "optionalSignature", OCSPRequest.defaultValues("optionalSignature"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "tbsRequest":
return new TBSRequest();
case "optionalSignature":
return new Signature();
default:
throw new Error(`Invalid member name for OCSPRequest class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "tbsRequest":
// noinspection OverlyComplexBooleanExpressionJS
return ((TBSRequest.compareWithDefault("tbs", memberValue.tbs)) &&
(TBSRequest.compareWithDefault("version", memberValue.version)) &&
(TBSRequest.compareWithDefault("requestorName", memberValue.requestorName)) &&
(TBSRequest.compareWithDefault("requestList", memberValue.requestList)) &&
(TBSRequest.compareWithDefault("requestExtensions", memberValue.requestExtensions)));
case "optionalSignature":
return ((Signature.compareWithDefault("signatureAlgorithm", memberValue.signatureAlgorithm)) &&
(Signature.compareWithDefault("signature", memberValue.signature)) &&
(Signature.compareWithDefault("certs", memberValue.certs)));
default:
throw new Error(`Invalid member name for OCSPRequest class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OCSPRequest ::= SEQUENCE {
* tbsRequest TBSRequest,
* optionalSignature [0] EXPLICIT Signature OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [tbsRequest]
* @property {string} [optionalSignature]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: names.blockName || "OCSPRequest",
value: [
TBSRequest.schema(names.tbsRequest || {
names: {
blockName: "tbsRequest"
}
}),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
Signature.schema(names.optionalSignature || {
names: {
blockName: "optionalSignature"
}
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"tbsRequest",
"optionalSignature"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OCSPRequest.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OCSPRequest");
//endregion
//region Get internal properties from parsed schema
this.tbsRequest = new TBSRequest({ schema: asn1.result.tbsRequest });
if("optionalSignature" in asn1.result)
this.optionalSignature = new Signature({ schema: asn1.result.optionalSignature });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @param {boolean} encodeFlag If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts.
* @returns {Object} asn1js object
*/
toSchema(encodeFlag = false)
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(this.tbsRequest.toSchema(encodeFlag));
if("optionalSignature" in this)
outputArray.push(this.optionalSignature.toSchema());
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
tbsRequest: this.tbsRequest.toJSON()
};
if("optionalSignature" in this)
_object.optionalSignature = this.optionalSignature.toJSON();
return _object;
}
//**********************************************************************************
/**
* Making OCSP Request for specific certificate
* @param {Certificate} certificate Certificate making OCSP Request for
* @param {Object} parameters Additional parameters
* @returns {Promise}
*/
createForCertificate(certificate, parameters)
{
//region Initial variables
let sequence = Promise.resolve();
const certID = new CertID();
//endregion
//region Create OCSP certificate identifier for the certificate
sequence = sequence.then(() =>
certID.createForCertificate(certificate, parameters)
);
//endregion
//region Make final request data
sequence = sequence.then(() =>
{
this.tbsRequest = new TBSRequest({
requestList: [
new Request({
reqCert: certID
})
]
});
}, error =>
Promise.reject(error)
);
//endregion
return sequence;
}
//**********************************************************************************
/**
* Make signature for current OCSP Request
* @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
* @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
* @returns {Promise}
*/
sign(privateKey, hashAlgorithm = "SHA-1")
{
//region Initial checking
//region Check private key
if(typeof privateKey === "undefined")
return Promise.reject("Need to provide a private key for signing");
//endregion
//region Check that "optionalSignature" exists in the current request
if(("optionalSignature" in this) === false)
return Promise.reject("Need to create \"optionalSignature\" field before signing");
//endregion
//endregion
//region Initial variables
let sequence = Promise.resolve();
let parameters;
let tbs;
const engine = getEngine();
//endregion
//region Get a "default parameters" for current algorithm and set correct signature algorithm
sequence = sequence.then(() => engine.subtle.getSignatureParameters(privateKey, hashAlgorithm));
sequence = sequence.then(result =>
{
parameters = result.parameters;
this.optionalSignature.signatureAlgorithm = result.signatureAlgorithm;
});
//endregion
//region Create TBS data for signing
sequence = sequence.then(() =>
{
tbs = this.tbsRequest.toSchema(true).toBER(false);
});
//endregion
//region Signing TBS data on provided private key
sequence = sequence.then(() => engine.subtle.signWithPrivateKey(tbs, privateKey, parameters));
sequence = sequence.then(result =>
{
this.optionalSignature.signature = new asn1js.BitString({ valueHex: result });
});
//endregion
return sequence;
}
//**********************************************************************************
verify()
{
// TODO: Create the function
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,299 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import ResponseBytes from "./ResponseBytes.js";
import BasicOCSPResponse from "./BasicOCSPResponse.js";
//**************************************************************************************
/**
* Class from RFC6960
*/
export default class OCSPResponse
{
//**********************************************************************************
/**
* Constructor for OCSPResponse class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {Enumerated}
* @desc responseStatus
*/
this.responseStatus = getParametersValue(parameters, "responseStatus", OCSPResponse.defaultValues("responseStatus"));
if("responseBytes" in parameters)
/**
* @type {ResponseBytes}
* @desc responseBytes
*/
this.responseBytes = getParametersValue(parameters, "responseBytes", OCSPResponse.defaultValues("responseBytes"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "responseStatus":
return new asn1js.Enumerated();
case "responseBytes":
return new ResponseBytes();
default:
throw new Error(`Invalid member name for OCSPResponse class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "responseStatus":
return (memberValue.isEqual(OCSPResponse.defaultValues(memberName)));
case "responseBytes":
return ((ResponseBytes.compareWithDefault("responseType", memberValue.responseType)) &&
(ResponseBytes.compareWithDefault("response", memberValue.response)));
default:
throw new Error(`Invalid member name for OCSPResponse class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OCSPResponse ::= SEQUENCE {
* responseStatus OCSPResponseStatus,
* responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
*
* OCSPResponseStatus ::= ENUMERATED {
* successful (0), -- Response has valid confirmations
* malformedRequest (1), -- Illegal confirmation request
* internalError (2), -- Internal error in issuer
* tryLater (3), -- Try again later
* -- (4) is not used
* sigRequired (5), -- Must sign the request
* unauthorized (6) -- Request unauthorized
* }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [responseStatus]
* @property {string} [responseBytes]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || "OCSPResponse"),
value: [
new asn1js.Enumerated({ name: (names.responseStatus || "responseStatus") }),
new asn1js.Constructed({
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [
ResponseBytes.schema(names.responseBytes || {
names: {
blockName: "responseBytes"
}
})
]
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"responseStatus",
"responseBytes"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OCSPResponse.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OCSPResponse");
//endregion
//region Get internal properties from parsed schema
this.responseStatus = asn1.result.responseStatus;
if("responseBytes" in asn1.result)
this.responseBytes = new ResponseBytes({ schema: asn1.result.responseBytes });
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(this.responseStatus);
if("responseBytes" in this)
{
outputArray.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: [this.responseBytes.toSchema()]
}));
}
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
responseStatus: this.responseStatus.toJSON()
};
if("responseBytes" in this)
_object.responseBytes = this.responseBytes.toJSON();
return _object;
}
//**********************************************************************************
/**
* Get OCSP response status for specific certificate
* @param {Certificate} certificate
* @param {Certificate} issuerCertificate
* @returns {*}
*/
getCertificateStatus(certificate, issuerCertificate)
{
//region Initial variables
let basicResponse;
const result = {
isForCertificate: false,
status: 2 // 0 = good, 1 = revoked, 2 = unknown
};
//endregion
//region Check that "ResponseBytes" contain "OCSP_BASIC_RESPONSE"
if(("responseBytes" in this) === false)
return result;
if(this.responseBytes.responseType !== "1.3.6.1.5.5.7.48.1.1") // id-pkix-ocsp-basic
return result;
try
{
const asn1Basic = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
basicResponse = new BasicOCSPResponse({ schema: asn1Basic.result });
}
catch(ex)
{
return result;
}
//endregion
return basicResponse.getCertificateStatus(certificate, issuerCertificate);
}
//**********************************************************************************
/**
* Make a signature for current OCSP Response
* @param {Object} privateKey Private key for "subjectPublicKeyInfo" structure
* @param {string} [hashAlgorithm] Hashing algorithm. Default SHA-1
* @returns {Promise}
*/
sign(privateKey, hashAlgorithm)
{
//region Check that ResponseData has type BasicOCSPResponse and sign it
if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1")
{
const asn1 = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
const basicResponse = new BasicOCSPResponse({ schema: asn1.result });
return basicResponse.sign(privateKey, hashAlgorithm);
}
return Promise.reject(`Unknown ResponseBytes type: ${this.responseBytes.responseType}`);
//endregion
}
//**********************************************************************************
/**
* Verify current OCSP Response
* @param {Certificate|null} issuerCertificate In order to decrease size of resp issuer cert could be ommited. In such case you need manually provide it.
* @returns {Promise}
*/
verify(issuerCertificate = null)
{
//region Check that ResponseBytes exists in the object
if(("responseBytes" in this) === false)
return Promise.reject("Empty ResponseBytes field");
//endregion
//region Check that ResponceData has type BasicOCSPResponse and verify it
if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1")
{
const asn1 = asn1js.fromBER(this.responseBytes.response.valueBlock.valueHex);
const basicResponse = new BasicOCSPResponse({ schema: asn1.result });
if(issuerCertificate !== null)
{
if(("certs" in basicResponse) === false)
basicResponse.certs = [];
basicResponse.certs.push(issuerCertificate);
}
return basicResponse.verify();
}
return Promise.reject(`Unknown ResponseBytes type: ${this.responseBytes.responseType}`);
//endregion
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,228 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import IssuerAndSerialNumber from "./IssuerAndSerialNumber.js";
import OriginatorPublicKey from "./OriginatorPublicKey.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class OriginatorIdentifierOrKey
{
//**********************************************************************************
/**
* Constructor for OriginatorIdentifierOrKey class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {number}
* @desc variant
*/
this.variant = getParametersValue(parameters, "variant", OriginatorIdentifierOrKey.defaultValues("variant"));
if("value" in parameters)
/**
* @type {IssuerAndSerialNumber|OctetString|OriginatorPublicKey}
* @desc value
*/
this.value = getParametersValue(parameters, "value", OriginatorIdentifierOrKey.defaultValues("value"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "variant":
return (-1);
case "value":
return {};
default:
throw new Error(`Invalid member name for OriginatorIdentifierOrKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "variant":
return (memberValue === (-1));
case "value":
return (Object.keys(memberValue).length === 0);
default:
throw new Error(`Invalid member name for OriginatorIdentifierOrKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OriginatorIdentifierOrKey ::= CHOICE {
* issuerAndSerialNumber IssuerAndSerialNumber,
* subjectKeyIdentifier [0] SubjectKeyIdentifier,
* originatorKey [1] OriginatorPublicKey }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Choice({
value: [
IssuerAndSerialNumber.schema({
names: {
blockName: (names.blockName || "")
}
}),
new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
name: (names.blockName || "")
}),
new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
name: (names.blockName || ""),
value: OriginatorPublicKey.schema().valueBlock.value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"blockName"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OriginatorIdentifierOrKey.schema({
names: {
blockName: "blockName"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OriginatorIdentifierOrKey");
//endregion
//region Get internal properties from parsed schema
if(asn1.result.blockName.idBlock.tagClass === 1)
{
this.variant = 1;
this.value = new IssuerAndSerialNumber({ schema: asn1.result.blockName });
}
else
{
if(asn1.result.blockName.idBlock.tagNumber === 0)
{
//region Create "OCTETSTRING" from "ASN1_PRIMITIVE"
asn1.result.blockName.idBlock.tagClass = 1; // UNIVERSAL
asn1.result.blockName.idBlock.tagNumber = 4; // OCTETSTRING
//endregion
this.variant = 2;
this.value = asn1.result.blockName;
}
else
{
this.variant = 3;
this.value = new OriginatorPublicKey({
schema: new asn1js.Sequence({
value: asn1.result.blockName.valueBlock.value
})
});
}
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
switch(this.variant)
{
case 1:
return this.value.toSchema();
case 2:
this.value.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
this.value.idBlock.tagNumber = 0; // [0]
return this.value;
case 3:
{
const _schema = this.value.toSchema();
_schema.idBlock.tagClass = 3; // CONTEXT-SPECIFIC
_schema.idBlock.tagNumber = 1; // [1]
return _schema;
}
default:
return new asn1js.Any();
}
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
variant: this.variant
};
if((this.variant === 1) || (this.variant === 2) || (this.variant === 3))
_object.value = this.value.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,228 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import CertificateSet from "./CertificateSet.js";
import RevocationInfoChoices from "./RevocationInfoChoices.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class OriginatorInfo
{
//**********************************************************************************
/**
* Constructor for OriginatorInfo class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
if("certs" in parameters)
/**
* @type {CertificateSet}
* @desc certs
*/
this.certs = getParametersValue(parameters, "certs", OriginatorInfo.defaultValues("certs"));
if("crls" in parameters)
/**
* @type {RevocationInfoChoices}
* @desc crls
*/
this.crls = getParametersValue(parameters, "crls", OriginatorInfo.defaultValues("crls"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "certs":
return new CertificateSet();
case "crls":
return new RevocationInfoChoices();
default:
throw new Error(`Invalid member name for OriginatorInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "certs":
return (memberValue.certificates.length === 0);
case "crls":
return ((memberValue.crls.length === 0) && (memberValue.otherRevocationInfos.length === 0));
default:
throw new Error(`Invalid member name for OriginatorInfo class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OriginatorInfo ::= SEQUENCE {
* certs [0] IMPLICIT CertificateSet OPTIONAL,
* crls [1] IMPLICIT RevocationInfoChoices OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [certs]
* @property {string} [crls]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.Constructed({
name: (names.certs || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: CertificateSet.schema().valueBlock.value
}),
new asn1js.Constructed({
name: (names.crls || ""),
optional: true,
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: RevocationInfoChoices.schema().valueBlock.value
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"certs",
"crls"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OriginatorInfo.schema({
names: {
certs: "certs",
crls: "crls"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OriginatorInfo");
//endregion
//region Get internal properties from parsed schema
if("certs" in asn1.result)
{
this.certs = new CertificateSet({
schema: new asn1js.Set({
value: asn1.result.certs.valueBlock.value
})
});
}
if("crls" in asn1.result)
{
this.crls = new RevocationInfoChoices({
schema: new asn1js.Set({
value: asn1.result.crls.valueBlock.value
})
});
}
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
const sequenceValue = [];
if("certs" in this)
{
sequenceValue.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
value: this.certs.toSchema().valueBlock.value
}));
}
if("crls" in this)
{
sequenceValue.push(new asn1js.Constructed({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 1 // [1]
},
value: this.crls.toSchema().valueBlock.value
}));
}
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: sequenceValue
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {};
if("certs" in this)
object.certs = this.certs.toJSON();
if("crls" in this)
object.crls = this.crls.toJSON();
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,170 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
import AlgorithmIdentifier from "./AlgorithmIdentifier.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class OriginatorPublicKey
{
//**********************************************************************************
/**
* Constructor for OriginatorPublicKey class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {AlgorithmIdentifier}
* @desc algorithm
*/
this.algorithm = getParametersValue(parameters, "algorithm", OriginatorPublicKey.defaultValues("algorithm"));
/**
* @type {BitString}
* @desc publicKey
*/
this.publicKey = getParametersValue(parameters, "publicKey", OriginatorPublicKey.defaultValues("publicKey"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "algorithm":
return new AlgorithmIdentifier();
case "publicKey":
return new asn1js.BitString();
default:
throw new Error(`Invalid member name for OriginatorPublicKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "algorithm":
case "publicKey":
return (memberValue.isEqual(OriginatorPublicKey.defaultValues(memberName)));
default:
throw new Error(`Invalid member name for OriginatorPublicKey class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OriginatorPublicKey ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* publicKey BIT STRING }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [algorithm]
* @property {string} [publicKey]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
AlgorithmIdentifier.schema(names.algorithm || {}),
new asn1js.BitString({ name: (names.publicKey || "") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"algorithm",
"publicKey"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OriginatorPublicKey.schema({
names: {
algorithm: {
names: {
blockName: "algorithm"
}
},
publicKey: "publicKey"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OriginatorPublicKey");
//endregion
//region Get internal properties from parsed schema
this.algorithm = new AlgorithmIdentifier({ schema: asn1.result.algorithm });
this.publicKey = asn1.result.publicKey;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
this.algorithm.toSchema(),
this.publicKey
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
return {
algorithm: this.algorithm.toJSON(),
publicKey: this.publicKey.toJSON()
};
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,147 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class OtherCertificateFormat
{
//**********************************************************************************
/**
* Constructor for OtherCertificateFormat class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc otherCertFormat
*/
this.otherCertFormat = getParametersValue(parameters, "otherCertFormat", OtherCertificateFormat.defaultValues("otherCertFormat"));
/**
* @type {Any}
* @desc otherCert
*/
this.otherCert = getParametersValue(parameters, "otherCert", OtherCertificateFormat.defaultValues("otherCert"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "otherCertFormat":
return "";
case "otherCert":
return new asn1js.Any();
default:
throw new Error(`Invalid member name for OtherCertificateFormat class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OtherCertificateFormat ::= SEQUENCE {
* otherCertFormat OBJECT IDENTIFIER,
* otherCert ANY DEFINED BY otherCertFormat }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [otherCertFormat]
* @property {string} [otherCert]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.otherCertFormat || "otherCertFormat") }),
new asn1js.Any({ name: (names.otherCert || "otherCert") })
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"otherCertFormat",
"otherCert"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OtherCertificateFormat.schema()
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OtherCertificateFormat");
//endregion
//region Get internal properties from parsed schema
this.otherCertFormat = asn1.result.otherCertFormat.valueBlock.toString();
this.otherCert = asn1.result.otherCert;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: [
new asn1js.ObjectIdentifier({ value: this.otherCertFormat }),
this.otherCert
]
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const object = {
otherCertFormat: this.otherCertFormat
};
if(!(this.otherCert instanceof asn1js.Any))
object.otherCert = this.otherCert.toJSON();
return object;
}
//**********************************************************************************
}
//**************************************************************************************

View File

@@ -1,185 +0,0 @@
import * as asn1js from "./asn1.js";
import { getParametersValue, clearProps } from "./pvutils.js";
//**************************************************************************************
/**
* Class from RFC5652
*/
export default class OtherKeyAttribute
{
//**********************************************************************************
/**
* Constructor for OtherKeyAttribute class
* @param {Object} [parameters={}]
* @param {Object} [parameters.schema] asn1js parsed value to initialize the class from
*/
constructor(parameters = {})
{
//region Internal properties of the object
/**
* @type {string}
* @desc keyAttrId
*/
this.keyAttrId = getParametersValue(parameters, "keyAttrId", OtherKeyAttribute.defaultValues("keyAttrId"));
if("keyAttr" in parameters)
/**
* @type {*}
* @desc keyAttr
*/
this.keyAttr = getParametersValue(parameters, "keyAttr", OtherKeyAttribute.defaultValues("keyAttr"));
//endregion
//region If input argument array contains "schema" for this object
if("schema" in parameters)
this.fromSchema(parameters.schema);
//endregion
}
//**********************************************************************************
/**
* Return default values for all class members
* @param {string} memberName String name for a class member
*/
static defaultValues(memberName)
{
switch(memberName)
{
case "keyAttrId":
return "";
case "keyAttr":
return {};
default:
throw new Error(`Invalid member name for OtherKeyAttribute class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Compare values with default values for all class members
* @param {string} memberName String name for a class member
* @param {*} memberValue Value to compare with default value
*/
static compareWithDefault(memberName, memberValue)
{
switch(memberName)
{
case "keyAttrId":
return (memberValue === "");
case "keyAttr":
return (Object.keys(memberValue).length === 0);
default:
throw new Error(`Invalid member name for OtherKeyAttribute class: ${memberName}`);
}
}
//**********************************************************************************
/**
* Return value of pre-defined ASN.1 schema for current class
*
* ASN.1 schema:
* ```asn1
* OtherKeyAttribute ::= SEQUENCE {
* keyAttrId OBJECT IDENTIFIER,
* keyAttr ANY DEFINED BY keyAttrId OPTIONAL }
* ```
*
* @param {Object} parameters Input parameters for the schema
* @returns {Object} asn1js schema object
*/
static schema(parameters = {})
{
/**
* @type {Object}
* @property {string} [blockName]
* @property {string} [optional]
* @property {string} [keyAttrId]
* @property {string} [keyAttr]
*/
const names = getParametersValue(parameters, "names", {});
return (new asn1js.Sequence({
optional: (names.optional || true),
name: (names.blockName || ""),
value: [
new asn1js.ObjectIdentifier({ name: (names.keyAttrId || "") }),
new asn1js.Any({
optional: true,
name: (names.keyAttr || "")
})
]
}));
}
//**********************************************************************************
/**
* Convert parsed asn1js object into current class
* @param {!Object} schema
*/
fromSchema(schema)
{
//region Clear input data first
clearProps(schema, [
"keyAttrId",
"keyAttr"
]);
//endregion
//region Check the schema is valid
const asn1 = asn1js.compareSchema(schema,
schema,
OtherKeyAttribute.schema({
names: {
keyAttrId: "keyAttrId",
keyAttr: "keyAttr"
}
})
);
if(asn1.verified === false)
throw new Error("Object's schema was not verified against input data for OtherKeyAttribute");
//endregion
//region Get internal properties from parsed schema
this.keyAttrId = asn1.result.keyAttrId.valueBlock.toString();
if("keyAttr" in asn1.result)
this.keyAttr = asn1.result.keyAttr;
//endregion
}
//**********************************************************************************
/**
* Convert current object to asn1js object and set correct values
* @returns {Object} asn1js object
*/
toSchema()
{
//region Create array for output sequence
const outputArray = [];
outputArray.push(new asn1js.ObjectIdentifier({ value: this.keyAttrId }));
if("keyAttr" in this)
outputArray.push(this.keyAttr);
//endregion
//region Construct and return new ASN.1 schema for this object
return (new asn1js.Sequence({
value: outputArray
}));
//endregion
}
//**********************************************************************************
/**
* Convertion for the class to JSON object
* @returns {Object}
*/
toJSON()
{
const _object = {
keyAttrId: this.keyAttrId
};
if("keyAttr" in this)
_object.keyAttr = this.keyAttr.toJSON();
return _object;
}
//**********************************************************************************
}
//**************************************************************************************

Some files were not shown because too many files have changed in this diff Show More