Verify a signature using a certificate RSA Javascript - javascript
I am attempting to verify a signature with a certificate. We have to download the required certificate from the CA, verify the certificate, then verify the signature. I have no idea, and I'm hoping someone can shed some light. Here's what I have / know so far.
To sign a message, I used the following code:
function sign(sk, m, certname) {
var key = new RSAKey();
key.setPrivate(sk.n, sk.e, sk.d);
var h = CryptoJS.SHA256(JSON.stringify(m)).toString(CryptoJS.enc.Hex);
h = new BigInteger(h, 16);
var sig = key.doPrivate(h).toString(16);
var obj = { "type": "SIGNED", "msg": m, "certname": certname, "sig": sig };
return JSON.stringify(obj);
}
To verify a signature, I used the following code:
function verify(pk, signed) {
var key = new RSAKey();
var s = JSON.stringify(signed.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(pk.n, pk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signed.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}
To verify a certificate, I used the following code: (EDIT: this is the new certificate verification function).
function verifyCertificate(signedCert, certname) {
var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);
return (v == h);
}
And that's that. Can anyone please help. I don't know how to go about this.
EDIT: Okay, I think I have solved my own question (with assistance from the responses). This is the code that returns all positive results:
function verifyWithCert(sig) {
// 1. Download the required certificate from the CA
// 2. Verify the certificate
// 3. Verify the message
var certKey = new RSAKey();
var loadedCert = loadCert(sig.certname);
var certS = JSON.stringify(loadedCert.sig).toString(CryptoJS.enc.Hex);
certS = new BigInteger(certS, 16);
certKey.setPublic(CApk.n, CApk.e);
var certV = certKey.doPublic(certS).toString(16);
var certH = CryptoJS.SHA256(JSON.stringify(loadedCert.msg)).toString(CryptoJS.enc.Hex);
var verifyResult;
if (certV == certH) {
verifyResult = true;
}
var Sigkey = new RSAKey();
var s = JSON.stringify(sig.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
Sigkey.setPublic(loadedCert.msg.subject.pk.n, loadedCert.msg.subject.pk.e);
var v = Sigkey.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(sig.msg)).toString(CryptoJS.enc.Hex);
var verifySignature;
if (v == h) {
verifySignature = true;
}
var result = { "certificateFound": loadedCert ,"certificateVerified": verifyResult ,"signatureVerified": verifySignature };
return result;
}
(A note to other members of StackOverflow, I am also in this class so there's a bit of stuff that I mention that comes out of nowhere in regards to variables and other references.)
In the verifyCertificate function:
function verifyCertificate(signedCert, certname) {
var loadedCert = loadCert(certname);
// signedCert is the same as loadedCert above, the button runs the
// loadCert function and outputs the contents into the textarea,
// so the following will always be true.
var originalSig = JSON.stringify(signedCert.sig);
var loadedSig = JSON.stringify(loadedCert.sig);
log(loadedSig);
return (originalSig == loadedSig);
}
How am I supposed to verify the certificate then? What am I comparing the loaded CA certificate to? I thought maybe compare the public key in the certificate to the public key used to sign the message but... I don't know. I'm very confused.
You're on the right track with that though, think about the verify() function, and the details contained in the CApk variable at the top of the file. Can you hash the message from the loadCert() JSON response and match it against the output from:
function verify() {
//[...]
key.setPublic(pk.n, pk.e);
//[...]
}
Assuming you change a few variables?
It's similar to the method I used at least, so I'm hoping it's right. I figure if you can hash the message using the details in CApk, and compare it to a hash of the message contained in the JSON response, that verifies the certificate. Hopefully.
There is an error in 'verify certificate' approach.
you need to test the signature of certificate with public key of CA given in 355a3_main to verify, the code given here will only verify your certificate and will give s false positive for rest
i think this should work
var loadedCert = loadCert(certname);
var originalSig = JSON.stringify(signedCert.sig);
var loadedSig = JSON.stringify(loadedCert.sig);
log(loadedSig,originalSig);
var key = new RSAKey();
var s = JSON.stringify(signedCert.sig).toString(CryptoJS.enc.Hex);
s = new BigInteger(s, 16);
key.setPublic(CApk.n, CApk.e);
var v = key.doPublic(s).toString(16);
var h = CryptoJS.SHA256(JSON.stringify(signedCert.msg)).toString(CryptoJS.enc.Hex);
if (originalSig == loadedSig && v==h)
return true;
else
return false;
That being said what about the long message of arbitrary length?
Except... you know how he says his solutions for the core tasks are between 5 and 10 lines? well this is about 20 lines of code, so i don't know if I should be suspicious of my code
I used the function verify and verifycertificate again in the RSA signature verification with certificate function. That will make your code fairly short. and I really appreciate this post, you're all my life savers.
Related
Is there anyway to change the path of a blob from URL.createObjectURL
I am using GMS1.4 HTML5 module and i'm currently trying to import sprite images to it. The issue is i don't want to save it in the local directory and since there is a built in function that allows the sprite to be added from a URL i was thinking of just using a blob to get the job done so the temp sprite is erased from memory after the user is done with the game. The problem is 1.4 is sandboxed so all url links and references seems to point to the Local storage. instead of blob:http://mysite.co/85cad96e-e44e-a1f9-db97a96ed3fe it'll preapped like this http://mysite.co/html5game/blob:http://mysite/85cad96e-e44e-a1f9-db97a96ed3fe Im only assuming its due to the sandbox nature of GMS and there does not seem to be a way to turn it off. my next idea is since it wants to be stubborn about using the sandbox directory, was to just create the blob within that folder. Is it possible to create at path and URL.createObjectURL?
You could adapt an approach based on what I did for "Allow Data URI" to also allow blob URIs. Excerpt follows, GML: #define gmcallback_AllowDataURI if (AllowDataURI()) { AllowDataURI(sprite_add("", 1, 0, 0, 0, 0)); } JS: function AllowDataURI() { var p0 = "\\s*\\(\\s*"; var p1 = "\\s*\\)\\s*"; var eq = "\\s*=\\s*"; var id = "\\w+"; // var init_js = window.gml_Script_gmcallback_AllowDataURI.toString(); var sprite_add_js = window[ /\bAllowDataURI\s*\(\s*(\w+)/.exec(init_js)[1] // AllowDataURI(sprite_add(... ].toString(); var sprite_add_url = /function\s*\w*\s*\((\w+)/g.exec(sprite_add_js)[1]; var sprite_add_url2 = new RegExp( "("+id+")"+eq+sprite_add_url+"\\b", // `sprite_add_url2 = sprite_add_url` "g").exec(sprite_add_js); sprite_add_url2 = sprite_add_url2 ? sprite_add_url2[1] : sprite_add_url; // var image_add_js = window[new RegExp( id+eq+"("+id+")"+p0+sprite_add_url2+p1, // `_ = image_add(sprite_add_url2)` "g").exec(sprite_add_js)[1]].toString(); var image_add_url = /function\s*\w*\s*\((\w+)/g.exec(image_add_js)[1]; // var url_proc = new RegExp( id+eq+"("+id+")"+p0+image_add_url+p1, // `_ = url_proc(image_add_url)` "g").exec(image_add_js)[1]; window[url_proc] = (function() { var f = window[url_proc]; return function(url) { if (url.substring(0, 5) == "data:") return url; if (url.substring(0, 5) == "blob:") return url; // new! return f.apply(this, arguments); }; })(); // return false; }
Antlr4 Javascript Visitor
I'm currently trying to develope a JavaScript Compiler with the help of an Antlr4 Visitor. I've got this already implemented with Java but cannot figure out how to do this in JavaScript. Probably somebody can answer me a few questions? 1: In Java there is a Visitor.visit function. If im right this isn't possibile with Javascript. Is there a work around for this? 2: My Javascript Visitor got all the generated visiting functions but when I use console.log(ctx) the context is undefined. Any idea why? Extract from the SimpleVisitor.js: // Visit a parse tree produced by SimpleParser#parse. SimpleVisitor.prototype.visitParse = function(ctx) { console.log(ctx); }; Main js file: var antlr4 = require('lib/antlr4/index'); var SimpleLexer = require('antlr4/SimpleLexer'); var SimpleParser = require('antlr4/SimpleParser'); var SimpleVisitor = require('antlr4/SimpleVisitor'); var input = "double hallo = 1;"; var chars = new antlr4.InputStream(input); var lexer = new SimpleLexer.SimpleLexer(chars); var tokens = new antlr4.CommonTokenStream(lexer); var parser = new SimpleParser.SimpleParser(tokens); var visitor = new SimpleVisitor.SimpleVisitor(); parser.buildParseTrees = true; var tree = parser.parse(); visitor.visitParse(); This is probably enough to start with ... Bruno Edit: Probably the context is undefined because I call the function without arguments but where do I get the "starting"-context? Edit2: So I think I get the idea how this should work out. One Question remaining how do I determine which rule to call next inside each visitor function?
The basic idea behind the visitor is that you have to handle all the logic by yourself. To do this I generated the visitor using antlr. My own visitor overrides all functions that I need to implement my logic. create lexer, tokens, ... var antlr4 = require('antlr4/index'); var SimpleJavaLexer = require('generated/GrammarLexer'); var SimpleJavaParser = require('generated/GrammarParser'); var SimpleJavaVisitor = require('generated/GrammarVisitor'); var Visitor = require('./Visitor'); var input = "TestInput"; var chars = new antlr4.InputStream(input); var lexer = new GrammarLexer.GrammarLexer(chars); var tokens = new antlr4.CommonTokenStream(lexer); var parser = new GrammarParser.GrammarParser(tokens); var visitor = new Visitor.Visitor(); parser.buildParseTrees = true; var tree = parser.parse(); and call your entry function visitor.visitTest(tree); inside your new visitor you need to implement your new logic to determine which function to call next (the right context as argument is important) var GrammarVisitor = require('generated/GrammarVisitor').GrammarVisitor; function Visitor () { SimpleJavaVisitor.call(this); return this; }; Visitor.prototype = Object.create(GrammarVisitor.prototype); Visitor.prototype.constructor = Visitor; Visitor.prototype.visitTest = function(ctx) { // implement logic to determine which function to visit // then call next function and with the right context this.visitBlock(ctx.block()); }; I hope you can understand my basic idea. If anybody got any questions just comment.
Is there a way of Creating lnk file using javascript
I would like to give the users in my website the ability to download a "lnk" file. My idea is to generate this file with to contain an address that can be used only once. Is there a way to generate this file in javascript? The flow is something like - the user presses a button the javascript generates this file and downloads it to the user's machine the user sends this file to another user to use this one-time-address from his machine Is something like this is doable in javascript from the client side? or would i need to generate this file using java server side?
This is a faithful translation of mslink.sh. I only tested my answer in Windows 8.1, but I would think that it works in older versions of Windows, too. function create_lnk_blob(lnk_target) { function hex_to_arr(s) { var result = Array(s.length / 2); for (var i = 0; i < result.length; ++i) { result[i] = +('0x' + s.substr(2*i, 2)); } return result; } function str_to_arr(s) { var result = Array(s.length); for (var i = 0; i < s.length; ++i) { var c = s.charCodeAt(i); if (c >= 128) { throw Error("Only ASCII paths are suppored :-("); } result[i] = c; } return result; } function convert_CLSID_to_DATA(s) { var idx = [[6,2], [4,2], [2,2], [0,2], [11,2], [9,2], [16,2], [14,2], [19,4], [24,12]]; var s = idx.map(function (ii) { return s.substr(ii[0], ii[1]); }); return hex_to_arr(s.join('')); } function gen_IDLIST(s) { var item_size = (0x10000 + s.length + 2).toString(16).substr(1); return hex_to_arr(item_size.replace(/(..)(..)/, '$2$1')).concat(s); } var HeaderSize = [0x4c, 0x00,0x00,0x00], LinkCLSID = convert_CLSID_to_DATA("00021401-0000-0000-c000-000000000046"), LinkFlags = [0x01,0x01,0x00,0x00], // HasLinkTargetIDList ForceNoLinkInfo FileAttributes_Directory = [0x10,0x00,0x00,0x00], FileAttributes_File = [0x20,0x00,0x00,0x00], CreationTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], AccessTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], WriteTime = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], FileSize = [0x00,0x00,0x00,0x00], IconIndex = [0x00,0x00,0x00,0x00], ShowCommand = [0x01,0x00,0x00,0x00], //SW_SHOWNORMAL Hotkey = [0x00,0x00], // No Hotkey Reserved = [0x00,0x00], Reserved2 = [0x00,0x00,0x00,0x00], Reserved3 = [0x00,0x00,0x00,0x00], TerminalID = [0x00,0x00], CLSID_Computer = convert_CLSID_to_DATA("20d04fe0-3aea-1069-a2d8-08002b30309d"), CLSID_Network = convert_CLSID_to_DATA("208d2c60-3aea-1069-a2d7-08002b30309d"), PREFIX_LOCAL_ROOT = [0x2f], PREFIX_FOLDER = [0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], PREFIX_FILE = [0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], PREFIX_NETWORK_ROOT = [0xc3,0x01,0x81], PREFIX_NETWORK_PRINTER = [0xc3,0x02,0xc1], END_OF_STRING = [0x00]; if (/.*\\+$/.test(lnk_target)) { lnk_target = lnk_target.replace(/\\+$/g, ''); var target_is_folder = true; } var prefix_root, item_data, target_root, target_leaf; if (lnk_target.substr(0, 2) === '\\\\') { prefix_root = PREFIX_NETWORK_ROOT; item_data = [0x1f, 0x58].concat(CLSID_Network); target_root = lnk_target.subtr(lnk_target.lastIndexOf('\\')); if (/\\\\.*\\.*/.test(lnk_target)) { target_leaf = lnk_target.substr(lnk_target.lastIndexOf('\\') + 1); } if (target_root === '\\') { target_root = lnk_target; } } else { prefix_root = PREFIX_LOCAL_ROOT; item_data = [0x1f, 0x50].concat(CLSID_Computer); target_root = lnk_target.replace(/\\.*$/, '\\'); if (/.*\\.*/.test(lnk_target)) { target_leaf = lnk_target.replace(/^.*?\\/, ''); } } var prefix_of_target, file_attributes; if (!target_is_folder) { prefix_of_target = PREFIX_FILE; file_attributes = FileAttributes_File; } else { prefix_of_target = PREFIX_FOLDER; file_attributes = FileAttributes_Directory; } target_root = str_to_arr(target_root); for (var i = 1; i <= 21; ++i) { target_root.push(0); } var id_list_items = gen_IDLIST(item_data); id_list_items = id_list_items.concat( gen_IDLIST(prefix_root.concat(target_root, END_OF_STRING))); if (target_leaf) { target_leaf = str_to_arr(target_leaf); id_list_items = id_list_items.concat( gen_IDLIST(prefix_of_target.concat(target_leaf, END_OF_STRING))); } var id_list = gen_IDLIST(id_list_items); var data = [].concat(HeaderSize, LinkCLSID, LinkFlags, file_attributes, CreationTime, AccessTime, WriteTime, FileSize, IconIndex, ShowCommand, Hotkey, Reserved, Reserved2, Reserved3, id_list, TerminalID); return new Blob([new Uint8Array(data)], { type: 'application/x-ms-shortcut' }); } var blob = create_lnk_blob('C:\\Windows\\System32\\Calc.exe'); Use it like: var blob_to_file = create_lnk_blob('C:\\Windows\\System32\\Calc.exe'); var blob_to_folder = create_lnk_blob('C:\\Users\\Myself\\Desktop\\'); // with a trailing slash Demo: http://jsfiddle.net/5cjgLyan/2/
This would be simple if your website allows php. If your script is part of an html file, just write the the javascript as if you were writing it to send a static lnk file. Then, at the lnk address part, break apart the javascript into two parts, breaking into html. Then at that point, put in <?php /*PHP code set a variable *? /* PHP code to generate proper string*/ PRINT /*PHP variable*/ ?>
I think make it pure client is impossible. Even the web rtc protocol need at least one iceServer to signal other client. And I think the easiest way to do that is use http://peerjs.com/ you could first create a clinet token of the room owner //room owner side peer.on('open', function(my_peer_id) { console.log('My peer ID is: ' + my_peer_id); }); And send the token to any other you want (by text file, web chat ...etc) Then other connect it use the token above //the other one var conn = peer.connect(other_peer_id); After the room owner detected someone entered the room. Disconnect from signal server, so the token will become unusable //room owner side peer.disconnect() About generate and read file by client side, I recommend you read article below. http://www.html5rocks.com/en/tutorials/file/dndfiles/ read from file How to use filesaver.js save as file I believe the compatibility of fileReader api and blob doesn't matter. Since there will never be a browser which support webrtc but not support fileReader api
Is it possible send my object with methods (function) from server to client?
I have object whith method (function) on server (node.js). I want get this object with methods in browser. Is it possible? I made simple example on GitHub There are server.js and index.html files. Run --> node server. ++++++++ UPD (after comments) My object on server: function ClassOrder(name, cost) { this.name = name; this.cost = cost; this.parts = []; this.summ = function() { var summ = 0; this.parts.forEach(function(part) { summ += part.summ(); }); return summ + this.cost; }; } var myobject = new ClassOrder('my object', 10); myobject.parts[0] = new ClassOrder('my first part', 20); myobject.parts[1] = new ClassOrder('my second part', 30); myobject.parts[1].parts[0] = new ClassOrder('my first in second part', 40); console.log(myobject); // view myobject in console console.log(myobject.summ()); // return 100 (10+20+30+40) send to client (on request) res.end(JSON.stringify(myobject)); and get it on client's javascript code (in browser) function getobject() { var xhr = new XMLHttpRequest(); xhr.open('get', '/getobject', true); xhr.onreadystatechange = function() { if (xhr.readyState != 4) return; var myobject = JSON.parse(this.responseText); console.log(myobject); // all data ok console.log(myobject.summ()); // no methods!! }; xhr.send(null); } It is a simple example and in real i use prototype (or inherit in util(node.js)). I use this methods on server and save it in DB. All work is ok. But if i wont use it on client i need copy-paste all methods, WHY? Also i dont know how add my example method to my object in client without disassemble it.
The question was: how can I get on server and client identical objects with methods without doublecoding. There are two way do it. The first way is convert my methods (function) to text and save it with object. Then we can use Function constructor to run it. function ClassOrder(name, cost) { this.name = name; this.cost = cost; this.parts = []; this.summfunc = '\ var summ=0; \ obj.parts.forEach(function(part) { \ summ += part.summ(); \ }); \ return summ + obj.cost;'; } ClassOrder.prototype.summ = function() { return (new Function('obj', this.summfunc))(this); }; and can use it in browser var myobject = JSON.parse(this.responseText); myobject.constructor.prototype.summ = function() { return (new Function('obj', this.summfunc))(this); }; Link to commit on new branch on GItHub This way is bad because i need all my methods convert to text. And how say #Felix Kling it makes the code harder to maintain and follow. The second way is use one file with classes and methods on server and on client. And ufter receive data "convert" it to my class. my class in file order.js (part of file): function Order(object) { object.parts = object.parts || []; var partsArr = []; object.parts.forEach(function (value, key) { partsArr[key] = new Order(value); }); this.name = object.name || 'Default'; this.cost = object.cost || 0; this.parts = partsArr; } Order.prototype.summ = function() { var summ = 0; this.parts.forEach(function(part) { summ += part.summ(); }); return summ + this.cost; }; require order.js and change arguments of call new Object: var Order = require('./order') var myobject = new Order({name:'my object', cost: 10}); myobject.parts[0] = new Order({name:'my first part', cost: 20}); myobject.parts[1] = new Order({name:'my second part', cost: 30}); myobject.parts[1].parts[0] = new Order({name:'my first in second part', cost: 40}); and finaly use this file on client: <script src='order.js'></script> ... var xhrobj = JSON.parse(this.responseText); var myobject = new Order(xhrobj); Link to commit on other branch on GItHub I think this way is better then first.
I think the answer is right there: Calling a JavaScript function returned from an Ajax response But it seems that isn't necessary to put the answers in a script tag, try this: eval(this.responseText)
Use JScript to insert Price List on Quote onOpen in Microsoft Dynamics CRM 2011
Here is my code, I get an object error onLoad. Please help. function Setlook() { var lookup = new Object(); var lookupValue = new Array(); lookup.id = "7b31D4D998-F124-E111-96C3-1CC1DEEA"; lookup.entityType = 1022; lookup.name = "Default"; lookupValue[0] = lookup; Xrm.Page.getAttribute(“pricelevelid”).setValue(lookupValue); }
The code itself looks correct, but the GUID of the lookup doesn't. It doesn't have the right format nor does it have the right number of characters (32). Fixing that should eliminate the error.
Here is the proper syntax, the important thing is to have the correct .typename function Setlook() { var value = new Array(); value[0] = new Object(); value[0].id = '{31D4D998-F124-E111-96C3-1CC1DEE8EC2D}'; value[0].name = 'Default'; value[0].typename = 'pricelevel'; Xrm.Page.getAttribute("pricelevelid").setValue(value); }