mirror of
https://github.com/tlsnotary/PageSigner.git
synced 2026-01-09 14:48:07 -05:00
pgsgV4 - the notary commits to server write key/IV (for easier verification). Encrypt all communication with notary. Add tlsnotarygroup9 notary. Allow pgsgV3 to be imported.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
"name": "PageSigner",
|
||||
"description": "PageSigner - a cryptographically secure webpage screenshot tool",
|
||||
"version": "2.0.1",
|
||||
"version": "2.1.0",
|
||||
"author": "TLSNotary Group",
|
||||
|
||||
"permissions": [
|
||||
|
||||
@@ -176,6 +176,14 @@ function openManager() {
|
||||
|
||||
|
||||
async function prepareNotarizing(after_click) {
|
||||
if (!oracles_intact) {
|
||||
sendAlert({
|
||||
title: 'PageSigner error',
|
||||
text: 'Cannot notarize because something is wrong with PageSigner server. Please try again later'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var clickTimeout = null;
|
||||
|
||||
var active_tab = await new Promise(function(resolve, reject) {
|
||||
@@ -492,15 +500,6 @@ async function import_resource(filename) {
|
||||
|
||||
|
||||
async function startNotarizing(headers, server, port) {
|
||||
if (!oracles_intact) {
|
||||
//NotarizeAfterClick already changed the icon at this point, revert to normal
|
||||
loadNormalIcon();
|
||||
sendAlert({
|
||||
title: 'PageSigner error',
|
||||
text: 'Cannot notarize because something is wrong with PageSigner server. Please try again later'
|
||||
});
|
||||
return;
|
||||
}
|
||||
loadBusyIcon();
|
||||
try{
|
||||
let rv = await start_audit(server, port, headers);
|
||||
@@ -529,43 +528,44 @@ async function startNotarizing(headers, server, port) {
|
||||
|
||||
|
||||
async function save_session(args) {
|
||||
|
||||
assert(args.length === 11, "wrong args length");
|
||||
var idx = -1;
|
||||
var client_random = args[idx+=1]
|
||||
var server_random= args[idx+=1]
|
||||
var server_certchain = args[idx+=1]
|
||||
var rsa_sig = args[idx+=1]
|
||||
var client_random = args[idx+=1]
|
||||
var server_random = args[idx+=1]
|
||||
var ec_pubkey_server = args[idx+=1]
|
||||
var ec_pubkey_client = args[idx+=1]
|
||||
var server_write_key = args[idx+=1]
|
||||
var server_write_IV = args[idx+=1]
|
||||
var server_response = args[idx+=1]
|
||||
var cleartext = args[idx+=1]
|
||||
var notary_signature = args[idx+=1]
|
||||
var ec_privkey = args[idx+=1]
|
||||
var time = args[idx+=1]
|
||||
|
||||
var pgsg_json = {}
|
||||
pgsg_json["title"] = "PageSigner notarization file"
|
||||
pgsg_json["version"] = 3
|
||||
pgsg_json["client random"] = b64encode(client_random)
|
||||
pgsg_json["server random"] = b64encode(server_random)
|
||||
pgsg_json["version"] = 4
|
||||
pgsg_json["certificate chain"] = {}
|
||||
for (let [idx, cert] of server_certchain.entries()) {
|
||||
let key = 'cert'+idx.toString()
|
||||
pgsg_json["certificate chain"][key] = b64encode(cert)
|
||||
}
|
||||
pgsg_json["server RSA signature over EC pubkey"] = b64encode(rsa_sig)
|
||||
pgsg_json['client random'] = b64encode(client_random)
|
||||
pgsg_json['server random'] = b64encode(server_random)
|
||||
pgsg_json["server EC pubkey"] = b64encode(ec_pubkey_server)
|
||||
pgsg_json["client EC pubkey"] = b64encode(ec_pubkey_client)
|
||||
pgsg_json["server write key"] = b64encode(server_write_key)
|
||||
pgsg_json["server write IV"] = b64encode(server_write_IV)
|
||||
pgsg_json["server response"] = b64encode(server_response)
|
||||
pgsg_json["notary signature"] = b64encode(notary_signature)
|
||||
pgsg_json["client EC privkey"] = b64encode(ec_privkey)
|
||||
pgsg_json["notarization time"] = b64encode(time)
|
||||
pgsg_json["notary name"] = chosen_notary.name
|
||||
var pgsg = pgsg_json
|
||||
|
||||
var commonName = getCommonName(server_certchain[0]);
|
||||
var creationTime = getTime();
|
||||
await createNewSession (creationTime, commonName, cleartext, pgsg, false);
|
||||
await createNewSession (creationTime, commonName, chosen_notary.name, cleartext, pgsg, false);
|
||||
return creationTime; //creationTime is also a session ID
|
||||
}
|
||||
|
||||
@@ -637,10 +637,79 @@ function convertPgsg(data){
|
||||
}
|
||||
|
||||
|
||||
async function verifyPgsg(json){
|
||||
if (json['version'] == 3){
|
||||
return await verifyPgsgV3(json);
|
||||
}
|
||||
else if (json['version'] == 4){
|
||||
return await verifyPgsgV4(json);
|
||||
}
|
||||
else {
|
||||
throw ('Unrecognized version of the imported pgsg file.')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//pgsg is in json
|
||||
async function verifyPgsg(json) {
|
||||
async function verifyPgsgV4(json) {
|
||||
var server_write_key = b64decode(json['server write key'])
|
||||
var server_write_IV = b64decode(json['server write IV'])
|
||||
var chain = []
|
||||
var certNumber = Object.keys(json['certificate chain']).length
|
||||
for (var i=0; i<certNumber; i++){
|
||||
let key = 'cert' + i.toString()
|
||||
chain.push(b64decode(json['certificate chain'][key]))
|
||||
}
|
||||
var rsa_sig = b64decode(json['server RSA signature over EC pubkey'])
|
||||
var client_random = b64decode(json['client random'])
|
||||
var server_random = b64decode(json['server random'])
|
||||
var ec_pubkey_server = b64decode(json['server EC pubkey'])
|
||||
var server_response = b64decode(json['server response'])
|
||||
var notary_signature = b64decode(json['notary signature'])
|
||||
var time = b64decode(json['notarization time'])
|
||||
var notaryName = json["notary name"]
|
||||
var notary;
|
||||
if (notaryName == oracle.name){
|
||||
notary = oracle;
|
||||
}
|
||||
else{
|
||||
var rv = await verifyOldOracle(notaryName);
|
||||
if (rv.result == true){
|
||||
notary = rv.oracle;
|
||||
}
|
||||
else{
|
||||
throw('unrecognized oracle in the imported file')
|
||||
}
|
||||
}
|
||||
|
||||
var seconds = ba2int(time)
|
||||
var date = new Date(seconds*1000)
|
||||
var commonName = getCommonName(chain[0]);
|
||||
var vcrv = await verifyChain(chain, date);
|
||||
if (vcrv[0] != true) {
|
||||
throw ('certificate verification failed');
|
||||
}
|
||||
var rv = await verifyECParamsSig(chain[0], ec_pubkey_server, rsa_sig, client_random, server_random)
|
||||
if (rv != true){
|
||||
throw ('EC parameters signature verification failed');
|
||||
}
|
||||
|
||||
var commit_hash = await sha256(server_response)
|
||||
//check notary server signature
|
||||
var signed_data_ba = await sha256([].concat(ec_pubkey_server, server_write_key, server_write_IV, commit_hash, time))
|
||||
assert(await verifyNotarySig(notary_signature, notary.pubkeyPEM, signed_data_ba) == true)
|
||||
//aesgcm decrypt the data
|
||||
var cleartext = await decrypt_tls_response (server_response, server_write_key, server_write_IV)
|
||||
var dechunked = dechunk_http(ba2str(cleartext))
|
||||
var ungzipped = gunzip_http(dechunked)
|
||||
return [ungzipped, commonName, notaryName];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//pgsg is in json
|
||||
async function verifyPgsgV3(json) {
|
||||
var client_random = b64decode(json['client random'])
|
||||
var server_random = b64decode(json['server random'])
|
||||
var chain = []
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
var oracles_intact = false; //must be explicitely set to true
|
||||
|
||||
var oracle = {
|
||||
var old_oracle = {
|
||||
'snapshotId': 'snap-0f838cf4591ac24e0',
|
||||
'imageId': 'ami-0a93db37bec3fda42',
|
||||
'name': 'tlsnotarygroup8',
|
||||
'IP': '34.229.208.191',
|
||||
'port': '10011',
|
||||
'DI':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstances&Expires=2025-01-01&InstanceId=i-0c4f98aeeac5308da&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=jjGBh1uwmvK2CQ%2B1WRwFCZ9FIVeAnRWErdBPd3JV4g4%3D',
|
||||
'DV':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeVolumes&Expires=2025-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&VolumeId=vol-075589b4c06dce11b&Signature=fmvB1pROTMbwjVyFm87F1DyCKKIgSirfzOYkdbbH4cA%3D',
|
||||
'GCO':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=GetConsoleOutput&Expires=2025-01-01&InstanceId=i-0c4f98aeeac5308da&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=cHCEeTBpKVOErTJeK254MbCGJJA9SreZb9HxW2fc2Cg%3D',
|
||||
'GU':'https://iam.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=GetUser&Expires=2025-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-05-08&Signature=N%2BsdNA6z3QReVsHsf7RV4uZLzS5Pqi0n3QSfqBAMs8o%3D',
|
||||
'DIAud':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=userData&Expires=2025-01-01&InstanceId=i-0c4f98aeeac5308da&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=mu8lWuB688ouVOkSL7M5ZS0y%2FLCcxMME4%2Bg6iikS5TE%3D',
|
||||
'DIAk':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=kernel&Expires=2025-01-01&InstanceId=i-0c4f98aeeac5308da&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=MmEJF7Ic4eOnWeH%2BGyheVApqKh8mrQX2rwQabiyvWhw%3D',
|
||||
'DIAr':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=ramdisk&Expires=2025-01-01&InstanceId=i-0c4f98aeeac5308da&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=IqNgbD%2FlGhvYQ8ndbMCz3PMFQjeGqBPvTU83repfJEs%3D',
|
||||
'DImg':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeImages&Expires=2025-01-01&ImageId.1=ami-0a93db37bec3fda42&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=xFhBqWoOyltYXRv%2F5SDCMfQBpDXFH2QPQBkgQahE8Ic%3D',
|
||||
'instanceId': 'i-0c4f98aeeac5308da',
|
||||
'pubkeyPEM': '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1XR5GYA7XmgMqH87HNaay4Xlzozs\nRflEv4VHWchpJteey5MRTn31e+pycFpOdaw6ybH8qfzkml1apoSl8+mO2A==\n-----END PUBLIC KEY-----'
|
||||
}
|
||||
|
||||
//until we deploy tlsnotarygroup9 this is just a placeholder
|
||||
var old_oracle = {
|
||||
// 'snapshotId': 'snap-0f838cf4591ac24e0',
|
||||
// 'imageId': 'ami-0a93db37bec3fda42',
|
||||
// 'name': 'tlsnotarygroup7',
|
||||
// 'IP': '34.229.208.191',
|
||||
// 'port': '10011',
|
||||
// 'instanceId': 'i-0c4f98aeeac5308da',
|
||||
// 'pubkeyPEM': '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1XR5GYA7XmgMqH87HNaay4Xlzozs\nRflEv4VHWchpJteey5MRTn31e+pycFpOdaw6ybH8qfzkml1apoSl8+mO2A==\n-----END PUBLIC KEY-----'
|
||||
var oracle = {
|
||||
'snapshotId': 'snap-0bf942f29a64f0f50',
|
||||
'imageId': 'ami-016509fc994427733',
|
||||
'name': 'tlsnotarygroup9',
|
||||
'IP': '35.174.184.105',
|
||||
'port': '10011',
|
||||
'DI':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstances&Expires=2025-01-01&InstanceId=i-04f8cbc53fcc36f1d&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=v9cJaD1mkA%2FP5VbyfpxuZlwgCazeac9dA0QMCWUoDkQ%3D',
|
||||
'DV':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeVolumes&Expires=2025-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&VolumeId=vol-05e08c73b01abe269&Signature=QAZk8%2BTdnRCeIeUMa10WufH2tmHdzzHT3Fi5VdLPnik%3D',
|
||||
'GCO':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=GetConsoleOutput&Expires=2025-01-01&InstanceId=i-04f8cbc53fcc36f1d&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=g9t%2FcEduhoLrr9kOEMm0dxqSq%2F5%2F8vhEM3QXHh%2Fzu5g%3D',
|
||||
'GU':'https://iam.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=GetUser&Expires=2025-01-01&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-05-08&Signature=N%2BsdNA6z3QReVsHsf7RV4uZLzS5Pqi0n3QSfqBAMs8o%3D',
|
||||
'DIAud':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=userData&Expires=2025-01-01&InstanceId=i-04f8cbc53fcc36f1d&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=akyi3eDbFSjsumu%2BHUjBV4bgKyZBvbQPyfSI26SzCF4%3D',
|
||||
'DIAk':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=kernel&Expires=2025-01-01&InstanceId=i-04f8cbc53fcc36f1d&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=1RtprpwQlU62ILIdN70WjsdnLnq9Eh2u0KSX7dnXpg8%3D',
|
||||
'DIAr':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeInstanceAttribute&Attribute=ramdisk&Expires=2025-01-01&InstanceId=i-04f8cbc53fcc36f1d&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=qPP8A7QKvH0PHpEBYzusz4efaB5zalc49IwxG1NfHfE%3D',
|
||||
'DImg':'https://ec2.us-east-1.amazonaws.com/?AWSAccessKeyId=AKIAIHZGACNJKBHFWOTQ&Action=DescribeImages&Expires=2025-01-01&ImageId.1=ami-016509fc994427733&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2014-10-01&Signature=HZKaD7ue3HE9e34F7pWmw5CeYvjidgV%2FOi6hrbvX2JQ%3D',
|
||||
'instanceId': 'i-04f8cbc53fcc36f1d',
|
||||
'pubkeyPEM': '-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaXM2Lxec8G3XJ6P86J3Qng+DKNzP\n0zGPlI7AqNLr+kCZ0obomrcvGS8QO0xyAVUaqK+oNIWFVKQf6LZPwP9m4w==\n-----END PUBLIC KEY-----'
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//there can be potentially multiple oracles to choose from
|
||||
var oracles = [];
|
||||
oracles.push(oracle);
|
||||
@@ -57,6 +56,7 @@ function getSecondsDelta(later, sooner) {
|
||||
|
||||
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;
|
||||
@@ -97,6 +97,7 @@ function checkDescribeInstances(xmlDoc, instanceId, IP, imageId) {
|
||||
|
||||
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];
|
||||
@@ -125,6 +126,7 @@ function checkDescribeVolumes(xmlDoc, instanceId, volumeId, volAttachTime, snaps
|
||||
|
||||
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
|
||||
@@ -165,6 +167,7 @@ function checkGetConsoleOutput(xmlDoc, instanceId, launchTime, pubkeyPEM) {
|
||||
// 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) {
|
||||
@@ -175,6 +178,7 @@ function checkDescribeInstanceAttributeUserdata(xmlDoc, instanceId) {
|
||||
|
||||
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) {
|
||||
@@ -185,6 +189,7 @@ function checkDescribeInstanceAttributeKernel(xmlDoc, instanceId) {
|
||||
|
||||
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) {
|
||||
@@ -196,6 +201,7 @@ function checkDescribeInstanceAttributeRamdisk(xmlDoc, instanceId) {
|
||||
|
||||
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) {
|
||||
@@ -206,16 +212,21 @@ function checkGetUser(xmlDoc, ownerId) {
|
||||
|
||||
|
||||
function checkDescribeImages(xmlDoc, imageId, snapshotId){
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -310,7 +321,7 @@ async function verifyOldOracle(name){
|
||||
if (rv == true){
|
||||
return {result:true, oracle:o};
|
||||
}
|
||||
return {{result:false};
|
||||
return {result:false};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
async function send_and_recv(command, data, expected_response, uid) {
|
||||
var url = "http://" + chosen_notary.IP + ":" + chosen_notary.port
|
||||
var payload = JSON.stringify({'request':command, 'uid': uid, 'data':b64encode(data)})
|
||||
var req = await fetch(url, {method:'POST', body: payload, cache: 'no-store'})
|
||||
try{
|
||||
var req = await fetch(url, {method:'POST', body: payload, cache: 'no-store'})
|
||||
}
|
||||
catch (err){
|
||||
throw('Could not connect to the PageSigner server. The error was:' + err)
|
||||
}
|
||||
var text_ab = await req.arrayBuffer()
|
||||
var text = ba2str(ab2ba(text_ab))
|
||||
console.log(text.length, text.slice(-100))
|
||||
@@ -201,12 +206,26 @@ const start_audit = async function(server, port, headers){
|
||||
|
||||
all_handshakes = all_handshakes.concat(shd)
|
||||
|
||||
var reply_data = await send_and_recv('cr_sr_spk_commpk', [].concat(
|
||||
client_random, server_random, ec_pubkey_server, commRawPubkey_ba), 'cpk_commpk', uid)
|
||||
var cpk = reply_data.slice(0,65) //Client's pubkey for ECDH
|
||||
var comm_pk = reply_data.slice(65,130) //Notary's EC pubkey for ECDH secret for communication
|
||||
|
||||
var reply_data_enc = await send_and_recv('cr_sr_spk_commpk', [].concat(
|
||||
client_random, server_random, ec_pubkey_server, commRawPubkey_ba), 'commpk_commpksig_cpk_cwk_cwi', uid)
|
||||
//communication pubkey is not encrypted
|
||||
//Notary's EC pubkey for ECDH secret for communication
|
||||
var comm_pk = reply_data_enc.slice(0,65)
|
||||
var commSymmetricKey = await getECDHSecret(comm_pk, commPrivkey)
|
||||
var reply_data = await decryptNotaryResponse(commSymmetricKey, reply_data_enc.slice(65))
|
||||
|
||||
var o = 0 //offset
|
||||
//get signature over communication pubkey
|
||||
var siglen = ba2int(reply_data.slice(o,o+=1))
|
||||
var commpk_sig = reply_data.slice(o, o+=siglen)
|
||||
//check signature
|
||||
var to_be_signed = await sha256(comm_pk)
|
||||
assert(await verifyNotarySig(commpk_sig, chosen_notary.pubkeyPEM, to_be_signed) == true)
|
||||
|
||||
var cpk = reply_data.slice(o,o+=65) //Client's pubkey for ECDH
|
||||
client_write_key = reply_data.slice(o, o+=16)
|
||||
client_write_IV = reply_data.slice(o, o+=4)
|
||||
|
||||
|
||||
//Send Client Key Exchange, Change Cipher Spec and Encrypted Handshake Message
|
||||
var cke_tls_record_header = [0x16, 0x03, 0x03, 0x00, 0x46] //Type: Handshake, Version: TLS 1.3, Length
|
||||
@@ -222,13 +241,13 @@ const start_audit = async function(server, port, headers){
|
||||
all_handshakes = [].concat(all_handshakes, cke)
|
||||
var hs_hash = await sha256(all_handshakes)
|
||||
|
||||
var reply_data_enc = await send_and_recv('hshash', hs_hash, 'vd_cwk_cwi', uid)
|
||||
var enc = await encryptNotaryRequest(commSymmetricKey, hs_hash)
|
||||
var reply_data_enc = await send_and_recv('hshash', enc, 'vd', uid)
|
||||
var reply_data = await decryptNotaryResponse(commSymmetricKey, reply_data_enc)
|
||||
|
||||
assert(reply_data.length == 32)
|
||||
assert(reply_data.length == 12)
|
||||
verify_data = reply_data.slice(0, 12)
|
||||
client_write_key = reply_data.slice(12, 28)
|
||||
client_write_IV = reply_data.slice(28, 32)
|
||||
|
||||
|
||||
var client_finished = await (async function encrypt_client_finished(){
|
||||
let finished = [].concat([0x14, 0x00, 0x00, 0x0c], verify_data) //Finished (0x14) with length 12
|
||||
@@ -281,7 +300,10 @@ const start_audit = async function(server, port, headers){
|
||||
//Send Server's encrypted Finished for decryption and Handshake hash to check server's verify data
|
||||
let hshash2 = await sha256(all_handshakes)
|
||||
|
||||
var reply_data = await send_and_recv('encf_hshash2', [].concat(enc_f, hshash2), 'verify_status', uid)
|
||||
var enc = await encryptNotaryRequest(commSymmetricKey, [].concat(enc_f, hshash2))
|
||||
var reply_data_enc = await send_and_recv('encf_hshash2', enc, 'verify_status', uid)
|
||||
var reply_data = await decryptNotaryResponse(commSymmetricKey, reply_data_enc)
|
||||
|
||||
assert(eq(reply_data, [0x01]))
|
||||
|
||||
|
||||
@@ -311,7 +333,8 @@ const start_audit = async function(server, port, headers){
|
||||
console.log('server_reply.length', server_reply.length)
|
||||
|
||||
var commit_hash = await sha256(server_reply)
|
||||
var reply_data_enc = await send_and_recv('commithash', commit_hash, 'swk_swi_sig_ecpriv_ecpub_time', uid)
|
||||
var enc = await encryptNotaryRequest(commSymmetricKey, commit_hash)
|
||||
var reply_data_enc = await send_and_recv('commithash', enc, 'swk_swi_sig_time', uid)
|
||||
var reply_data = await decryptNotaryResponse(commSymmetricKey, reply_data_enc)
|
||||
|
||||
var o = 0; //offset
|
||||
@@ -320,16 +343,12 @@ const start_audit = async function(server, port, headers){
|
||||
console.log('server_write_key, server_write_IV', server_write_key, server_write_IV)
|
||||
var sig_len = ba2int(reply_data.slice(o, o+=1))
|
||||
var notary_signature = reply_data.slice(o, o+=sig_len)
|
||||
var ec_privkey = reply_data.slice(o, o+=32)
|
||||
var ec_pubkey_client = reply_data.slice(o, o+=65)
|
||||
//we could derive ec_pubkey_client from ec_privkey but that would require an extra library.
|
||||
//Crypto.subtle refuses to import EC private key unless EC pubkey is also given
|
||||
var time = reply_data.slice(o, o+=4)
|
||||
console.log('resp.length', reply_data.length)
|
||||
assert(reply_data.length == o)
|
||||
|
||||
//Check notary server signature
|
||||
var signed_data = await sha256([].concat(ec_privkey, ec_pubkey_server, commit_hash, time))
|
||||
var signed_data = await sha256([].concat(ec_pubkey_server, server_write_key, server_write_IV, commit_hash, time))
|
||||
assert(await verifyNotarySig(notary_signature, chosen_notary.pubkeyPEM, signed_data) == true)
|
||||
|
||||
var cleartexts = await decrypt_tls_response(server_reply, server_write_key, server_write_IV)
|
||||
@@ -338,8 +357,7 @@ const start_audit = async function(server, port, headers){
|
||||
var ungzipped = gunzip_http(dechunked)
|
||||
console.log('ungzipped.length', ungzipped.length)
|
||||
|
||||
return [client_random, server_random, certs, rsa_sig, ec_pubkey_server,
|
||||
ec_pubkey_client, server_reply, ungzipped, notary_signature, ec_privkey, time ]
|
||||
return [certs, rsa_sig, client_random, server_random, ec_pubkey_server, server_write_key, server_write_IV, server_reply, ungzipped, notary_signature, time ]
|
||||
}
|
||||
|
||||
|
||||
@@ -354,6 +372,18 @@ async function decryptNotaryResponse (key, enc){
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
async function encryptNotaryRequest(key, cleartext){
|
||||
var IV = getRandom(12)
|
||||
var enc = await crypto.subtle.encrypt(
|
||||
{name: 'AES-GCM', iv: ba2ab(IV)},
|
||||
key,
|
||||
ba2ab(cleartext));
|
||||
var data = [].concat(IV, ab2ba(enc))
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//pub/privkey must be in WebCrypto format
|
||||
async function getExpandedKeys(hisPubkey, myPrivkey, cr, sr){
|
||||
var Secret = await crypto.subtle.deriveBits(
|
||||
|
||||
@@ -142,7 +142,7 @@ function ba2str(ba) {
|
||||
|
||||
|
||||
async function sha256(ba) {
|
||||
var digest = await crypto.subtle.digest('SHA-256', ba2ab(ba))
|
||||
var digest = await crypto.subtle.digest('SHA-256', ba2ab(ba))
|
||||
return (ab2ba(digest))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user