mirror of
https://gitlab.com/jusax23/ilmk.git
synced 2024-11-22 14:46:34 +01:00
Add crypto.js
This commit is contained in:
parent
95e600aeaf
commit
ef45e1a9fb
1 changed files with 327 additions and 0 deletions
327
crypto.js
Normal file
327
crypto.js
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
var node = false;
|
||||||
|
|
||||||
|
if (typeof require != "undefined") {
|
||||||
|
crypto = require('crypto');
|
||||||
|
if(typeof crypto.webcrypto != "undefined"){
|
||||||
|
crypto = crypto.webcrypto;
|
||||||
|
console.log("subtle");
|
||||||
|
}else{
|
||||||
|
node = true;
|
||||||
|
console.log("node crypto");
|
||||||
|
}
|
||||||
|
}/*else{
|
||||||
|
crypto = window.crypto;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
var asciiList = [];
|
||||||
|
for (var i = 0; i < 256; i++) {
|
||||||
|
asciiList[i]=String.fromCharCode(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const C = {
|
||||||
|
sha256: async (msgBuffer) => {
|
||||||
|
return node ? new Uint8Array(crypto.createHash("sha256").update(msgBuffer).digest()) :
|
||||||
|
new Uint8Array(await crypto.subtle.digest('SHA-256', msgBuffer));
|
||||||
|
},
|
||||||
|
random: async (length) => {
|
||||||
|
return node ? crypto.randomFillSync(new Uint8Array(length)) :
|
||||||
|
crypto.getRandomValues(new Uint8Array(length));
|
||||||
|
},
|
||||||
|
randomKey: async (length) => {
|
||||||
|
return C.decode(await C.random(length));
|
||||||
|
},
|
||||||
|
encode : (data)=>{
|
||||||
|
if(node){
|
||||||
|
return new Uint8Array(Buffer.from(data,"binary"));
|
||||||
|
}else{
|
||||||
|
var out = new Uint8Array(data.length);
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
out[i] = data.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return out;//new Uint8Array(data.split("").map(d => d.charCodeAt(0)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decode : (data)=>{
|
||||||
|
if(node){
|
||||||
|
return Buffer.from(data).toString("binary");
|
||||||
|
}else{
|
||||||
|
var out = [];
|
||||||
|
var i = 0;
|
||||||
|
var limit = i - (i%16);
|
||||||
|
while (i < limit) {
|
||||||
|
out.push(asciiList[data[i]]+asciiList[data[i+1]]+asciiList[data[i+2]]+asciiList[data[i+3]]+asciiList[data[i+4]]+asciiList[data[i+5]]+asciiList[data[i+6]]+asciiList[data[i+7]]+asciiList[data[i+8]]+asciiList[data[i+9]]+asciiList[data[i+10]]+asciiList[data[i+11]]+asciiList[data[i+12]]+asciiList[data[i+13]]+asciiList[data[i+14]]+asciiList[data[i+15]]);
|
||||||
|
i+=16;
|
||||||
|
}
|
||||||
|
while (i < data.length) {
|
||||||
|
out.push(asciiList[data[i]]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return out.join("");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
atob: (data)=>node?Buffer.from(data,"base64").toString("binary"):atob(data), //base to ascii
|
||||||
|
btoa: (data)=>node?Buffer.from(data,"binary").toString("base64"):btoa(data), //ascii to base
|
||||||
|
pad: (data) => {
|
||||||
|
var length = 16 - (data.length % 16);
|
||||||
|
var mergedArray = new Uint8Array(data.length+length);
|
||||||
|
mergedArray.set(data);
|
||||||
|
mergedArray.set(new Uint8Array(length).fill(length), data.length);
|
||||||
|
return mergedArray;
|
||||||
|
},
|
||||||
|
unpad: (data) => {
|
||||||
|
return data.slice(0, -data[data.length - 1]);
|
||||||
|
},
|
||||||
|
AES:{
|
||||||
|
bytes_to_key: async (bytes, salt, output = 48) => {
|
||||||
|
var data = new Uint8Array([...bytes, ...salt]);
|
||||||
|
var key = new Uint8Array();
|
||||||
|
var final_key = new Uint8Array();
|
||||||
|
while (final_key.length < output) {
|
||||||
|
key = await C.sha256(new Uint8Array([...key, ...data]));
|
||||||
|
final_key = new Uint8Array([...final_key, ...key]);
|
||||||
|
}
|
||||||
|
return final_key.slice(0, output);
|
||||||
|
},
|
||||||
|
encryptData: async (rawdata, rawkey) => {
|
||||||
|
var salt = await C.random(8);
|
||||||
|
var key_iv = await C.AES.bytes_to_key(rawkey, salt, 32 + 16);
|
||||||
|
var key = key_iv.slice(0, 32);
|
||||||
|
var iv = key_iv.slice(32);
|
||||||
|
var aes;
|
||||||
|
if(node){
|
||||||
|
let cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
||||||
|
let encrypted = cipher.update(C.pad(rawdata));
|
||||||
|
aes = new Uint8Array(Buffer.concat([encrypted, cipher.final()]));
|
||||||
|
}else{
|
||||||
|
aes = new Uint8Array(await crypto.subtle.encrypt({name: "AES-CBC",iv},await crypto.subtle.importKey("raw",key,"AES-CBC",true,["encrypt", "decrypt"]),C.pad(rawdata)));
|
||||||
|
}
|
||||||
|
var mergedArray = new Uint8Array(aes.length+16);
|
||||||
|
mergedArray.set([83, 97, 108, 116, 95, 50, 53, 54]);
|
||||||
|
mergedArray.set(salt,8);
|
||||||
|
mergedArray.set(aes,16);
|
||||||
|
return mergedArray;
|
||||||
|
},
|
||||||
|
encrypt: async (message, passphrase) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
var rawkey = C.encode(passphrase);
|
||||||
|
var step = await C.AES.encryptData(rawdata,rawkey);
|
||||||
|
return C.decode(step);
|
||||||
|
},
|
||||||
|
decryptData: async (rawdata, rawkey) => {
|
||||||
|
var check = [83, 97, 108, 116, 95, 50, 53, 54];
|
||||||
|
for (var i = 0; i < check.length; i++) {
|
||||||
|
if(check[i]!=rawdata[i])return null;
|
||||||
|
}
|
||||||
|
var salt = rawdata.slice(8,16);
|
||||||
|
var key_iv = await C.AES.bytes_to_key(rawkey, salt, 32 + 16);
|
||||||
|
var key = key_iv.slice(0, 32);
|
||||||
|
var iv = key_iv.slice(32);
|
||||||
|
if(node){
|
||||||
|
let cipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
|
||||||
|
let encrypted = cipher.update(rawdata.slice(16));
|
||||||
|
return C.unpad(new Uint8Array(Buffer.concat([encrypted, cipher.final()])));
|
||||||
|
}else{
|
||||||
|
return C.unpad(
|
||||||
|
new Uint8Array (await crypto.subtle.decrypt(
|
||||||
|
{name: "AES-CBC",iv},
|
||||||
|
await crypto.subtle.importKey("raw",key,"AES-CBC",true,["encrypt", "decrypt"]),
|
||||||
|
rawdata.slice(16)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
decrypt: async (message, passphrase) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
var rawkey = C.encode(passphrase);
|
||||||
|
try {
|
||||||
|
var step = await C.AES.decryptData(rawdata,rawkey);
|
||||||
|
return C.decode(step);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RSA:{
|
||||||
|
generateEncryptionKey: async () =>{
|
||||||
|
if(node){
|
||||||
|
var { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {modulusLength: 4096,publicExponent:0x010001,hashAlgorithm:"sha256"});
|
||||||
|
return {publicKey: C.decode(new Uint8Array( publicKey.export({type:"spki", format:"der"}))),
|
||||||
|
privateKey:C.decode(new Uint8Array(privateKey.export({type:"pkcs8",format:"der"})))};
|
||||||
|
}else{
|
||||||
|
var keyPair = await crypto.subtle.generateKey(
|
||||||
|
{name: "RSA-OAEP",modulusLength: 4096,publicExponent: new Uint8Array([1, 0, 1]),hash: "SHA-256"},
|
||||||
|
true,
|
||||||
|
["encrypt", "decrypt"]
|
||||||
|
);
|
||||||
|
return {privateKey:C.decode(new Uint8Array(await crypto.subtle.exportKey("pkcs8",keyPair.privateKey))),
|
||||||
|
publicKey: C.decode(new Uint8Array(await crypto.subtle.exportKey("spki", keyPair.publicKey )))};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generateSigningKey: async () =>{
|
||||||
|
if(node){
|
||||||
|
var { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {modulusLength: 4096,publicExponent:0x010001,hashAlgorithm:"sha256"});
|
||||||
|
return {publicKey: C.decode(new Uint8Array( publicKey.export({type:"spki", format:"der"}))),
|
||||||
|
privateKey:C.decode(new Uint8Array(privateKey.export({type:"pkcs8",format:"der"})))};
|
||||||
|
}else{
|
||||||
|
var keyPair = await crypto.subtle.generateKey(
|
||||||
|
{name: "RSA-PSS",modulusLength: 4096,publicExponent: new Uint8Array([1, 0, 1]),hash: "SHA-256"},
|
||||||
|
true,
|
||||||
|
["sign", "verify"]
|
||||||
|
);
|
||||||
|
return {privateKey:C.decode(new Uint8Array(await crypto.subtle.exportKey("pkcs8",keyPair.privateKey))),
|
||||||
|
publicKey: C.decode(new Uint8Array(await crypto.subtle.exportKey("spki", keyPair.publicKey )))};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
encrypt: async (message, publicKey) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
var step;
|
||||||
|
if(node){
|
||||||
|
var rawkey = crypto.createPublicKey({key:C.encode(publicKey),format:"der",type:"spki"});
|
||||||
|
//console.log("d",rawkey);
|
||||||
|
step = crypto.publicEncrypt({
|
||||||
|
key: rawkey,
|
||||||
|
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||||
|
oaepHash: "sha256",
|
||||||
|
}, Buffer.from(rawdata));
|
||||||
|
}else{
|
||||||
|
var rawkey = await crypto.subtle.importKey("spki",C.encode(publicKey),{name: "RSA-OAEP",hash: "SHA-256"},true,["encrypt"]);
|
||||||
|
step = await crypto.subtle.encrypt({name: "RSA-OAEP"},rawkey,rawdata);
|
||||||
|
}
|
||||||
|
return C.decode(new Uint8Array(step));
|
||||||
|
},
|
||||||
|
decrypt: async (message, privateKey) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
if(node){
|
||||||
|
var rawkey = crypto.createPrivateKey({key:C.encode(privateKey),format:"der",type:"pkcs8"});
|
||||||
|
try {
|
||||||
|
var step = crypto.privateDecrypt({
|
||||||
|
key: rawkey,
|
||||||
|
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
||||||
|
oaepHash: "sha256",
|
||||||
|
}, Buffer.from(rawdata));
|
||||||
|
return C.decode(new Uint8Array(step));
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var rawkey = await crypto.subtle.importKey("pkcs8",C.encode(privateKey),{name: "RSA-OAEP",hash: "SHA-256"},true,["decrypt"]);
|
||||||
|
try {
|
||||||
|
var step = await crypto.subtle.decrypt({name: "RSA-OAEP"},rawkey,rawdata);
|
||||||
|
return C.decode(new Uint8Array(step));
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
sign:async (message, privateKey) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
var step;
|
||||||
|
if(node){
|
||||||
|
var rawkey = crypto.createPrivateKey({key:C.encode(privateKey),format:"der",type:"pkcs8"});
|
||||||
|
step = crypto.sign("sha256", Buffer.from(rawdata), {
|
||||||
|
key: rawkey,
|
||||||
|
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
|
||||||
|
saltLength:32
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
var rawkey = await crypto.subtle.importKey("pkcs8",C.encode(privateKey),{name: "RSA-PSS",hash: "SHA-256"},true,["sign"]);
|
||||||
|
step = await crypto.subtle.sign(
|
||||||
|
{
|
||||||
|
name: "RSA-PSS",
|
||||||
|
saltLength: 32,
|
||||||
|
},
|
||||||
|
rawkey,
|
||||||
|
rawdata
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return C.decode(new Uint8Array(step));
|
||||||
|
},
|
||||||
|
verify:async (message, signature, publicKey) => {
|
||||||
|
var rawdata = C.encode(message);
|
||||||
|
var rawsig = C.encode(signature);
|
||||||
|
var step;
|
||||||
|
if(node){
|
||||||
|
var rawkey = crypto.createPublicKey({key:C.encode(publicKey),format:"der",type:"spki"});
|
||||||
|
step = crypto.verify(
|
||||||
|
"sha256",
|
||||||
|
Buffer.from(rawdata),
|
||||||
|
{
|
||||||
|
key: rawkey,
|
||||||
|
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
|
||||||
|
saltLength:32
|
||||||
|
},
|
||||||
|
Buffer.from(rawsig)
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
var rawkey = await crypto.subtle.importKey("spki",C.encode(publicKey),{name: "RSA-PSS",hash: "SHA-256"},true,["verify"]);
|
||||||
|
step = await crypto.subtle.verify(
|
||||||
|
{
|
||||||
|
name: "RSA-PSS",
|
||||||
|
saltLength: 32,
|
||||||
|
},
|
||||||
|
rawkey,
|
||||||
|
rawsig,
|
||||||
|
rawdata
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return step;// ? "valid" : "invalid";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
communicate:{
|
||||||
|
encrypt: async (message,publicKey)=>{
|
||||||
|
var randKey = await C.randomKey(32);
|
||||||
|
var send = {
|
||||||
|
d: await C.AES.encrypt(message,randKey),
|
||||||
|
k: await C.RSA.encrypt(randKey,publicKey)
|
||||||
|
};
|
||||||
|
return JSON.stringify(send);
|
||||||
|
},
|
||||||
|
decrypt: async (data,privateKey)=>{
|
||||||
|
try {
|
||||||
|
let {d,k} = JSON.parse(data);
|
||||||
|
if(typeof d != "string" || typeof k != "string")throw "invalid Data";
|
||||||
|
var randKey = await C.RSA.decrypt(k,privateKey);
|
||||||
|
if(randKey == null) throw "invalid async Key";
|
||||||
|
var out = await C.AES.decrypt(d,randKey);
|
||||||
|
if(out == null) throw "invalid sync Key";
|
||||||
|
return out;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//Message to send, reomte publicKey, own privateKey, my id so that the other one knows how i am (can be empty)
|
||||||
|
encryptSign: async (message,publicKey,privateKey,id)=>{
|
||||||
|
return await C.communicate.encrypt(JSON.stringify({
|
||||||
|
d:message,
|
||||||
|
i:id,
|
||||||
|
s:await C.RSA.sign(message,privateKey)
|
||||||
|
}),publicKey);
|
||||||
|
},
|
||||||
|
//Data to decrypt, my privateKey, callback to get reomtes publicKey with id
|
||||||
|
decryptSign: async (data,privateKey,publicKeyCall)=>{
|
||||||
|
try {
|
||||||
|
var inn = await C.communicate.decrypt(data,privateKey);
|
||||||
|
if(inn == null)throw "invalid privateKey";
|
||||||
|
inn = JSON.parse(inn);
|
||||||
|
if(typeof inn.d == "undefined"||typeof inn.i != "string"||typeof inn.s != "string") throw "invalid Data";
|
||||||
|
let {d,i,s} = inn;
|
||||||
|
var publicKey = publicKeyCall(i);
|
||||||
|
var okay = await C.RSA.verify(d,s,publicKey);
|
||||||
|
if(!okay) throw "wrong Public Key";
|
||||||
|
return d;
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(typeof module != "undefined"){
|
||||||
|
module.exports = C;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default C;
|
Loading…
Reference in a new issue