|
@@ -0,0 +1,145 @@
|
|
|
|
+import sjcl from 'sjcl';
|
|
|
|
+
|
|
|
|
+//везде недоработки...
|
|
|
|
+
|
|
|
|
+sjcl.codec.bytes = {
|
|
|
|
+ fromBits: function(arr) {
|
|
|
|
+ var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
|
|
|
|
+ for (i=0; i<bl/8; i++) {
|
|
|
|
+ if ((i&3) === 0) {
|
|
|
|
+ tmp = arr[i/4];
|
|
|
|
+ }
|
|
|
|
+ out.push(tmp >>> 24);
|
|
|
|
+ tmp <<= 8;
|
|
|
|
+ }
|
|
|
|
+ return out;
|
|
|
|
+ },
|
|
|
|
+ toBits: function(bytes) {
|
|
|
|
+ var out = [], i, tmp=0;
|
|
|
|
+ for (i=0; i<bytes.length; i++) {
|
|
|
|
+ tmp = tmp << 8 | bytes[i];
|
|
|
|
+ if ((i&3) === 3) {
|
|
|
|
+ out.push(tmp);
|
|
|
|
+ tmp = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (i&3) {
|
|
|
|
+ out.push(sjcl.bitArray.partial(8*(i&3), tmp));
|
|
|
|
+ }
|
|
|
|
+ return out;
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+sjcl.json._add = function(target, src, requireSame) {
|
|
|
|
+ if (target === undefined) { target = {}; }
|
|
|
|
+ if (src === undefined) { return target; }
|
|
|
|
+ var i;
|
|
|
|
+ for (i in src) {
|
|
|
|
+ if (src.hasOwnProperty(i)) {
|
|
|
|
+ if (requireSame && target[i] !== undefined && target[i] !== src[i]) {
|
|
|
|
+ throw new sjcl.exception.invalid("required parameter overridden");
|
|
|
|
+ }
|
|
|
|
+ target[i] = src[i];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return target;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sjcl.encryptArray = function(password, plaintext, params, rp) {
|
|
|
|
+ params = params || {};
|
|
|
|
+ rp = rp || {};
|
|
|
|
+
|
|
|
|
+ var j = sjcl.json, p = j._add({ iv: sjcl.random.randomWords(4,0) },
|
|
|
|
+ j.defaults), tmp, prp, adata;
|
|
|
|
+ j._add(p, params);
|
|
|
|
+ adata = p.adata;
|
|
|
|
+ if (typeof p.salt === "string") {
|
|
|
|
+ p.salt = sjcl.codec.base64.toBits(p.salt);
|
|
|
|
+ }
|
|
|
|
+ if (typeof p.iv === "string") {
|
|
|
|
+ p.iv = sjcl.codec.base64.toBits(p.iv);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!sjcl.mode[p.mode] ||
|
|
|
|
+ !sjcl.cipher[p.cipher] ||
|
|
|
|
+ (typeof password === "string" && p.iter <= 100) ||
|
|
|
|
+ (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
|
|
|
|
+ (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
|
|
|
|
+ (p.iv.length < 2 || p.iv.length > 4)) {
|
|
|
|
+ throw new sjcl.exception.invalid("json encrypt: invalid parameters");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (typeof password === "string") {
|
|
|
|
+ tmp = sjcl.misc.cachedPbkdf2(password, p);
|
|
|
|
+ password = tmp.key.slice(0,p.ks/32);
|
|
|
|
+ p.salt = tmp.salt;
|
|
|
|
+ } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.publicKey) {
|
|
|
|
+ tmp = password.kem();
|
|
|
|
+ p.kemtag = tmp.tag;
|
|
|
|
+ password = tmp.key.slice(0,p.ks/32);
|
|
|
|
+ }
|
|
|
|
+ if (typeof plaintext === "string") {
|
|
|
|
+ plaintext = sjcl.codec.utf8String.toBits(plaintext);
|
|
|
|
+ }
|
|
|
|
+ if (typeof adata === "string") {
|
|
|
|
+ p.adata = adata = sjcl.codec.utf8String.toBits(adata);
|
|
|
|
+ }
|
|
|
|
+ prp = new sjcl.cipher[p.cipher](password);
|
|
|
|
+
|
|
|
|
+ j._add(rp, p);
|
|
|
|
+ rp.key = password;
|
|
|
|
+
|
|
|
|
+ /* do the encryption */
|
|
|
|
+ if (p.mode === "ccm" && sjcl.arrayBuffer && sjcl.arrayBuffer.ccm && plaintext instanceof ArrayBuffer) {
|
|
|
|
+ p.ct = sjcl.arrayBuffer.ccm.encrypt(prp, plaintext, p.iv, adata, p.ts);
|
|
|
|
+ } else {
|
|
|
|
+ p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, adata, p.ts);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return p;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+sjcl.decryptArray = function(password, ciphertext, params) {
|
|
|
|
+ params = params || {};
|
|
|
|
+
|
|
|
|
+ var j = sjcl.json, p = j._add(j._add(j._add({},j.defaults),ciphertext), params, true), ct, tmp, prp, adata=p.adata;
|
|
|
|
+ if (typeof p.salt === "string") {
|
|
|
|
+ p.salt = sjcl.codec.base64.toBits(p.salt);
|
|
|
|
+ }
|
|
|
|
+ if (typeof p.iv === "string") {
|
|
|
|
+ p.iv = sjcl.codec.base64.toBits(p.iv);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!sjcl.mode[p.mode] ||
|
|
|
|
+ !sjcl.cipher[p.cipher] ||
|
|
|
|
+ (typeof password === "string" && p.iter <= 100) ||
|
|
|
|
+ (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
|
|
|
|
+ (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
|
|
|
|
+ (!p.iv) ||
|
|
|
|
+ (p.iv.length < 2 || p.iv.length > 4)) {
|
|
|
|
+ throw new sjcl.exception.invalid("json decrypt: invalid parameters");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (typeof password === "string") {
|
|
|
|
+ tmp = sjcl.misc.cachedPbkdf2(password, p);
|
|
|
|
+ password = tmp.key.slice(0,p.ks/32);
|
|
|
|
+ p.salt = tmp.salt;
|
|
|
|
+ } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.secretKey) {
|
|
|
|
+ password = password.unkem(sjcl.codec.base64.toBits(p.kemtag)).slice(0,p.ks/32);
|
|
|
|
+ }
|
|
|
|
+ if (typeof adata === "string") {
|
|
|
|
+ adata = sjcl.codec.utf8String.toBits(adata);
|
|
|
|
+ }
|
|
|
|
+ prp = new sjcl.cipher[p.cipher](password);
|
|
|
|
+
|
|
|
|
+ /* do the decryption */
|
|
|
|
+ if (p.mode === "ccm" && sjcl.arrayBuffer && sjcl.arrayBuffer.ccm && p.ct instanceof ArrayBuffer) {
|
|
|
|
+ ct = sjcl.arrayBuffer.ccm.decrypt(prp, p.ct, p.iv, p.tag, adata, p.ts);
|
|
|
|
+ } else {
|
|
|
|
+ ct = sjcl.mode[p.mode].decrypt(prp, p.ct, p.iv, adata, p.ts);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ct;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export default sjcl;
|