remove old files
@@ -1,8 +0,0 @@
|
||||
var link1 = document.getElementById("link1");
|
||||
link1.addEventListener("click", function(evt) {
|
||||
sendMessage({
|
||||
'destination': 'extension',
|
||||
'message': 'openLink1'
|
||||
});
|
||||
window.close();
|
||||
});
|
||||
|
Before Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 979 B |
@@ -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>
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 501 B |
@@ -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();
|
||||
};
|
||||
};
|
||||
})
|
||||
}
|
||||
|
Before Width: | Height: | Size: 543 B |
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -1,3 +0,0 @@
|
||||
GET /r/worldnews HTTP/1.1
|
||||
Host: www.reddit.com
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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);
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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);
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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 });
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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\"");
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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}`);
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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)
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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())
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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);
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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()
|
||||
};
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||
@@ -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;
|
||||
}
|
||||
//**********************************************************************************
|
||||
}
|
||||
//**************************************************************************************
|
||||