From 6e4d243897cdaefde0ccca2a0e65bb45e4c992f9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sun, 24 Apr 2016 21:49:14 +0300 Subject: [PATCH] Add uuid generation functions that uses high quality RNG. --- vendor/uuid/core.cljs | 25 +++++++++++++++++++++++ vendor/uuid/impl.js | 47 +++++++++++++++++++++++++++++++++++++++++++ vendor/uuid/rng.js | 44 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 vendor/uuid/core.cljs create mode 100644 vendor/uuid/impl.js create mode 100644 vendor/uuid/rng.js diff --git a/vendor/uuid/core.cljs b/vendor/uuid/core.cljs new file mode 100644 index 000000000..d81b5df17 --- /dev/null +++ b/vendor/uuid/core.cljs @@ -0,0 +1,25 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) 2016 Andrey Antukh + +(ns uuid.core + "Provides a UUID v4 uuid generation. + + In difference with builtin `random-uuid` function this + implementation tries to use high quality RNG if is + available (browser crypto object or nodejs crypto module). + + If no high qualiry RNG, switches to the default Math based + RNG with proper waring in the console." + (:require [uuid.impl :as impl])) + +(defn v4 + "Generate a v4 (random) UUID." + [] + (uuid (impl/v4))) + +(def random + "Alias for `uuid.core/v4`." + v4) diff --git a/vendor/uuid/impl.js b/vendor/uuid/impl.js new file mode 100644 index 000000000..b79b2f4d3 --- /dev/null +++ b/vendor/uuid/impl.js @@ -0,0 +1,47 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2016 Andrey Antukh +*/ +"use strict"; + +goog.provide("uuid.impl"); +goog.require("uuid.rng"); + +goog.scope(function() { + const rng = uuid.rng; + const hexMap = []; + + for (let i = 0; i < 256; i++) { + hexMap[i] = (i + 0x100).toString(16).substr(1); + } + + function toHexString(buf) { + let i = 0; + return (hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]] + '-' + + hexMap[buf[i++]] + + hexMap[buf[i++]] + '-' + + hexMap[buf[i++]] + + hexMap[buf[i++]] + '-' + + hexMap[buf[i++]] + + hexMap[buf[i++]] + '-' + + hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]] + + hexMap[buf[i++]]); + } + + uuid.impl.v4 = function() { + const buf = rng.getBytes(16); + buf[6] = (buf[6] & 0x0f) | 0x40; + buf[8] = (buf[8] & 0x3f) | 0x80; + return cljs.core.uuid(toHexString(buf)); + }; +}) diff --git a/vendor/uuid/rng.js b/vendor/uuid/rng.js new file mode 100644 index 000000000..be1c73ac7 --- /dev/null +++ b/vendor/uuid/rng.js @@ -0,0 +1,44 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2016 Andrey Antukh +*/ + +"use strict"; + +goog.provide("uuid.rng"); + +goog.scope(function() { + uuid.rng.getBytes = null; + + // Check if nodejs rng is available (high quality); + if (goog.global.require !== undefined) { + const crypto = goog.global.require("crypto"); + + uuid.rng.getBytes = function(n) { + return crypto.randomBytes(n); + }; + } + // Check if whatwg rng is available (high quality); + else if (goog.global.crypto.getRandomValues !== undefined) { + uuid.rng.getBytes = function(n) { + const buf = new Uint8Array(16); + goog.global.crypto.getRandomValues(buf); + return buf; + }; + } + // Switch Back to the Math.random (low quality); + else { + console.warn("No high quality RNG available, switching back to Math.random."); + uuid.rng.getBytes = function(n) { + const buf = new Array(16); + for (let i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) { r = Math.random() * 0x100000000; } + buf[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + return buf; + }; + } +});