aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-11-21 23:10:17 +0100
committerFlorian Dold <florian.dold@gmail.com>2019-11-21 23:10:24 +0100
commitde9f8867d5141940f47951c51648becec74959cb (patch)
tree84a1f224af86c5ca8fda65b12e22af741510c517 /src/crypto
parentc6233094306cd264f8faa2041388dff01ff8cf01 (diff)
downloadwallet-core-de9f8867d5141940f47951c51648becec74959cb.tar.xz
missing files / native encode/decode
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/nativeCrypto-test.ts32
-rw-r--r--src/crypto/nativeCrypto.ts140
2 files changed, 172 insertions, 0 deletions
diff --git a/src/crypto/nativeCrypto-test.ts b/src/crypto/nativeCrypto-test.ts
new file mode 100644
index 000000000..7b9fcf256
--- /dev/null
+++ b/src/crypto/nativeCrypto-test.ts
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports
+ */
+import test from "ava";
+import { encodeCrock, decodeCrock } from "./nativeCrypto";
+
+
+test("encoding", (t) => {
+ const utf8decoder = new TextDecoder("utf-8");
+ const utf8encoder = new TextEncoder();
+ const s = "Hello, World";
+ const encStr = encodeCrock(utf8encoder.encode(s));
+ const outBuf = decodeCrock(encStr);
+ const sOut = utf8decoder.decode(outBuf);
+ t.deepEqual(s, sOut);
+}); \ No newline at end of file
diff --git a/src/crypto/nativeCrypto.ts b/src/crypto/nativeCrypto.ts
new file mode 100644
index 000000000..853ece6c7
--- /dev/null
+++ b/src/crypto/nativeCrypto.ts
@@ -0,0 +1,140 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 GNUnet e.V.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Native implementation of GNU Taler crypto.
+ */
+
+let isNode;
+
+let myGetRandom: (n: number) => ArrayBuffer;
+
+if (require) {
+ // node.js
+ const cr = require("crypto");
+ myGetRandom = (n: number) => {
+ const buf = cr.randomBytes(n);
+ return Uint8Array.from(buf);
+ }
+} else {
+ // Browser
+ myGetRandom = (n: number) => {
+ const ret = new Uint8Array(n);
+ window.crypto.getRandomValues(ret);
+ return ret;
+ }
+}
+
+export function getRandomBytes(n: number): ArrayBuffer {
+ return myGetRandom(n);
+}
+
+const encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
+
+class EncodingError extends Error {
+ constructor() {
+ super("Encoding error");
+ Object.setPrototypeOf(this, EncodingError.prototype);
+ }
+}
+
+function getValue(chr: string): number {
+ let a = chr;
+ switch (chr) {
+ case "O":
+ case "o":
+ a = "0;";
+ break;
+ case "i":
+ case "I":
+ case "l":
+ case "L":
+ a = "1";
+ break;
+ case "u":
+ case "U":
+ a = "V";
+ }
+
+ if (a >= "0" && a <= "9") {
+ return a.charCodeAt(0) - "0".charCodeAt(0);
+ }
+
+ if (a >= "a" && a <= "z") a = a.toUpperCase();
+ let dec = 0;
+ if (a >= "A" && a <= "Z") {
+ if ("I" < a) dec++;
+ if ("L" < a) dec++;
+ if ("O" < a) dec++;
+ if ("U" < a) dec++;
+ return a.charCodeAt(0) - "A".charCodeAt(0) + 10 - dec;
+ }
+ throw new EncodingError();
+}
+
+export function encodeCrock(data: ArrayBuffer): string {
+ const dataBytes = new Uint8Array(data);
+ let sb = "";
+ const size = data.byteLength;
+ let bitBuf = 0;
+ let numBits = 0;
+ let pos = 0;
+ while (pos < size || numBits > 0) {
+ if (pos < size && numBits < 5) {
+ const d = dataBytes[pos++];
+ bitBuf = (bitBuf << 8) | d;
+ numBits += 8;
+ }
+ if (numBits < 5) {
+ // zero-padding
+ bitBuf = bitBuf << (5 - numBits);
+ numBits = 5;
+ }
+ const v = (bitBuf >>> (numBits - 5)) & 31;
+ sb += encTable[v];
+ numBits -= 5;
+ }
+ return sb;
+}
+
+export function decodeCrock(encoded: string): ArrayBuffer {
+ const size = encoded.length;
+ let bitpos = 0;
+ let bitbuf = 0;
+ let readPosition = 0;
+ const outLen = Math.floor((size * 5) / 8);
+ const out = new Int8Array(outLen);
+ let outPos = 0;
+
+ while (readPosition < size || bitpos > 0) {
+ //println("at position $readPosition with bitpos $bitpos")
+ if (readPosition < size) {
+ const v = getValue(encoded[readPosition++]);
+ bitbuf = (bitbuf << 5) | v;
+ bitpos += 5;
+ }
+ while (bitpos >= 8) {
+ const d = (bitbuf >>> (bitpos - 8)) & 0xff;
+ out[outPos++] = d;
+ bitpos -= 8;
+ }
+ if (readPosition == size && bitpos > 0) {
+ bitbuf = (bitbuf << (8 - bitpos)) & 0xff;
+ bitpos = bitbuf == 0 ? 0 : 8;
+ }
+ }
+ return out;
+}