| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 04c04c8 commit f9fdce3
12 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,24 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common.js'); | ||
| 4 | + const { createHmac } = require('crypto'); | ||
| 5 | + const assert = require('assert'); | ||
| 6 | + | ||
| 7 | + const bench = common.createBenchmark(main, { | ||
| 8 | + n: [1e5], | ||
| 9 | + algo: ['sha1', 'sha256', 'sha512'], | ||
| 10 | + keylen: [0, 16, 64, 1024], | ||
| 11 | + }); | ||
| 12 | + | ||
| 13 | + function main({ n, algo, keylen }) { | ||
| 14 | + const key = Buffer.alloc(keylen, 'k'); | ||
| 15 | + const hmacs = new Array(n); | ||
| 16 | + | ||
| 17 | + bench.start(); | ||
| 18 | + for (let i = 0; i < n; ++i) { | ||
| 19 | + hmacs[i] = createHmac(algo, key); | ||
| 20 | + } | ||
| 21 | + bench.end(n); | ||
| 22 | + | ||
| 23 | + assert.strictEqual(typeof hmacs[n - 1], 'object'); | ||
| 24 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,70 @@ | |||
| 1 | + // Throughput benchmark | ||
| 2 | + // creates a single HMAC, then pushes a bunch of data through it | ||
| 3 | + 'use strict'; | ||
| 4 | + | ||
| 5 | + const common = require('../common.js'); | ||
| 6 | + const { createHmac } = require('crypto'); | ||
| 7 | + | ||
| 8 | + const bench = common.createBenchmark(main, { | ||
| 9 | + n: [500], | ||
| 10 | + algo: ['sha1', 'sha256', 'sha512'], | ||
| 11 | + keylen: [64], | ||
| 12 | + type: ['asc', 'utf', 'buf'], | ||
| 13 | + len: [2, 1024, 102400, 1024 * 1024], | ||
| 14 | + api: ['update', 'stream'], | ||
| 15 | + }); | ||
| 16 | + | ||
| 17 | + function main({ api, type, len, algo, keylen, n }) { | ||
| 18 | + let message; | ||
| 19 | + let encoding; | ||
| 20 | + switch (type) { | ||
| 21 | + case 'asc': | ||
| 22 | + message = 'a'.repeat(len); | ||
| 23 | + encoding = 'ascii'; | ||
| 24 | + break; | ||
| 25 | + case 'utf': | ||
| 26 | + message = '\u00fc'.repeat(len / 2); | ||
| 27 | + encoding = 'utf8'; | ||
| 28 | + break; | ||
| 29 | + case 'buf': | ||
| 30 | + message = Buffer.alloc(len, 'b'); | ||
| 31 | + break; | ||
| 32 | + default: | ||
| 33 | + throw new Error(`unknown message type: ${type}`); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + const fn = api === 'stream' ? streamWrite : updateDigest; | ||
| 37 | + const key = Buffer.alloc(keylen, 'k'); | ||
| 38 | + | ||
| 39 | + bench.start(); | ||
| 40 | + fn(algo, key, message, encoding, n, len); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + function updateDigest(algo, key, message, encoding, n, len) { | ||
| 44 | + const written = n * len; | ||
| 45 | + const bits = written * 8; | ||
| 46 | + const gbits = bits / (1024 * 1024 * 1024); | ||
| 47 | + const h = createHmac(algo, key); | ||
| 48 | + | ||
| 49 | + while (n-- > 0) | ||
| 50 | + h.update(message, encoding); | ||
| 51 | + | ||
| 52 | + h.digest(); | ||
| 53 | + | ||
| 54 | + bench.end(gbits); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + function streamWrite(algo, key, message, encoding, n, len) { | ||
| 58 | + const written = n * len; | ||
| 59 | + const bits = written * 8; | ||
| 60 | + const gbits = bits / (1024 * 1024 * 1024); | ||
| 61 | + const h = createHmac(algo, key); | ||
| 62 | + | ||
| 63 | + while (n-- > 0) | ||
| 64 | + h.write(message, encoding); | ||
| 65 | + | ||
| 66 | + h.end(); | ||
| 67 | + h.read(); | ||
| 68 | + | ||
| 69 | + bench.end(gbits); | ||
| 70 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,80 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const common = require('../common.js'); | ||
| 4 | + const { subtle } = globalThis.crypto; | ||
| 5 | + | ||
| 6 | + const signParams = { name: 'HMAC' }; | ||
| 7 | + | ||
| 8 | + let keys; | ||
| 9 | + let currentHash; | ||
| 10 | + let currentKeyLength; | ||
| 11 | + | ||
| 12 | + const bench = common.createBenchmark(main, { | ||
| 13 | + hash: ['SHA-1', 'SHA-256', 'SHA-512'], | ||
| 14 | + mode: ['serial', 'parallel'], | ||
| 15 | + keyReuse: ['shared', 'unique'], | ||
| 16 | + keylen: [512], | ||
| 17 | + len: [0, 256, 4096], | ||
| 18 | + n: [1e3], | ||
| 19 | + }, { | ||
| 20 | + test: { | ||
| 21 | + keylen: 512, | ||
| 22 | + }, | ||
| 23 | + combinationFilter(p) { | ||
| 24 | + // Unique only differs from shared when operations overlap (parallel); | ||
| 25 | + // sequential calls have no contention so unique+serial adds no value. | ||
| 26 | + if (p.keyReuse === 'unique') return p.mode === 'parallel'; | ||
| 27 | + return true; | ||
| 28 | + }, | ||
| 29 | + }); | ||
| 30 | + | ||
| 31 | + async function createSigningKeys(n, hash, keylen) { | ||
| 32 | + keys = new Array(n); | ||
| 33 | + currentHash = hash; | ||
| 34 | + currentKeyLength = keylen; | ||
| 35 | + | ||
| 36 | + const algorithm = { name: 'HMAC', hash, length: keylen }; | ||
| 37 | + const key = await subtle.generateKey(algorithm, true, ['sign']); | ||
| 38 | + const raw = await subtle.exportKey('raw', key); | ||
| 39 | + for (let i = 0; i < n; ++i) { | ||
| 40 | + keys[i] = await subtle.importKey('raw', raw, algorithm, false, ['sign']); | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + async function measureSerial(n, sharedKey, data) { | ||
| 45 | + bench.start(); | ||
| 46 | + for (let i = 0; i < n; ++i) { | ||
| 47 | + await subtle.sign(signParams, sharedKey || keys[i], data); | ||
| 48 | + } | ||
| 49 | + bench.end(n); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + async function measureParallel(n, sharedKey, data) { | ||
| 53 | + const promises = new Array(n); | ||
| 54 | + bench.start(); | ||
| 55 | + for (let i = 0; i < n; ++i) { | ||
| 56 | + promises[i] = subtle.sign(signParams, sharedKey || keys[i], data); | ||
| 57 | + } | ||
| 58 | + await Promise.all(promises); | ||
| 59 | + bench.end(n); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + async function main({ n, mode, keyReuse, hash, keylen, len }) { | ||
| 63 | + if (!keys || keys.length !== n || | ||
| 64 | + currentHash !== hash || currentKeyLength !== keylen) { | ||
| 65 | + await createSigningKeys(n, hash, keylen); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + const data = new Uint8Array(len); | ||
| 69 | + data.fill(0x62); | ||
| 70 | + const sharedKey = keyReuse === 'shared' ? keys[0] : undefined; | ||
| 71 | + | ||
| 72 | + switch (mode) { | ||
| 73 | + case 'serial': | ||
| 74 | + await measureSerial(n, sharedKey, data); | ||
| 75 | + break; | ||
| 76 | + case 'parallel': | ||
| 77 | + await measureParallel(n, sharedKey, data); | ||
| 78 | + break; | ||
| 79 | + } | ||
| 80 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4629,6 +4629,7 @@ bool extractP1363(const Buffer<const unsigned char>& buf, | |||
| 4629 | 4629 | ||
| 4630 | 4630 | // ============================================================================ | |
| 4631 | 4631 | ||
| 4632 | + #if !OPENSSL_WITH_EVP_MAC | ||
| 4632 | 4633 | HMACCtxPointer::HMACCtxPointer() : ctx_(nullptr) {} | |
| 4633 | 4634 | ||
| 4634 | 4635 | HMACCtxPointer::HMACCtxPointer(HMAC_CTX* ctx) : ctx_(ctx) {} | |
@@ -4688,8 +4689,9 @@ bool HMACCtxPointer::digestInto(Buffer<void>* buf) { | |||
| 4688 | 4689 | HMACCtxPointer HMACCtxPointer::New() { | |
| 4689 | 4690 | return HMACCtxPointer(HMAC_CTX_new()); | |
| 4690 | 4691 | } | |
| 4692 | + #endif // !OPENSSL_WITH_EVP_MAC | ||
| 4691 | 4693 | ||
| 4692 | - #if OPENSSL_WITH_KMAC | ||
| 4694 | + #if OPENSSL_WITH_EVP_MAC | ||
| 4693 | 4695 | EVPMacPointer::EVPMacPointer(EVP_MAC* mac) : mac_(mac) {} | |
| 4694 | 4696 | ||
| 4695 | 4697 | EVPMacPointer::EVPMacPointer(EVPMacPointer&& other) noexcept | |
@@ -4777,7 +4779,92 @@ EVPMacCtxPointer EVPMacCtxPointer::New(EVP_MAC* mac) { | |||
| 4777 | 4779 | if (!mac) return EVPMacCtxPointer(); | |
| 4778 | 4780 | return EVPMacCtxPointer(EVP_MAC_CTX_new(mac)); | |
| 4779 | 4781 | } | |
| 4780 | - #endif // OPENSSL_WITH_KMAC | ||
| 4782 | + | ||
| 4783 | + HMACCtxPointer::HMACCtxPointer() = default; | ||
| 4784 | + | ||
| 4785 | + HMACCtxPointer::HMACCtxPointer(EVPMacPointer&& mac, EVPMacCtxPointer&& ctx) | ||
| 4786 | + : mac_(std::move(mac)), ctx_(std::move(ctx)) {} | ||
| 4787 | + | ||
| 4788 | + HMACCtxPointer::HMACCtxPointer(HMACCtxPointer&& other) noexcept | ||
| 4789 | + : mac_(std::move(other.mac_)), | ||
| 4790 | + ctx_(std::move(other.ctx_)), | ||
| 4791 | + md_size_(other.md_size_) { | ||
| 4792 | + other.md_size_ = 0; | ||
| 4793 | + } | ||
| 4794 | + | ||
| 4795 | + HMACCtxPointer& HMACCtxPointer::operator=(HMACCtxPointer&& other) noexcept { | ||
| 4796 | + if (this == &other) return *this; | ||
| 4797 | + mac_ = std::move(other.mac_); | ||
| 4798 | + ctx_ = std::move(other.ctx_); | ||
| 4799 | + md_size_ = other.md_size_; | ||
| 4800 | + other.md_size_ = 0; | ||
| 4801 | + return *this; | ||
| 4802 | + } | ||
| 4803 | + | ||
| 4804 | + HMACCtxPointer::~HMACCtxPointer() { | ||
| 4805 | + reset(); | ||
| 4806 | + } | ||
| 4807 | + | ||
| 4808 | + void HMACCtxPointer::reset() { | ||
| 4809 | + ctx_.reset(); | ||
| 4810 | + mac_.reset(); | ||
| 4811 | + md_size_ = 0; | ||
| 4812 | + } | ||
| 4813 | + | ||
| 4814 | + bool HMACCtxPointer::init(const Buffer<const void>& buf, const Digest& md) { | ||
| 4815 | + if (!ctx_ || !md) return false; | ||
| 4816 | + | ||
| 4817 | + const char* md_name = EVP_MD_get0_name(md); | ||
| 4818 | + if (md_name == nullptr) return false; | ||
| 4819 | + | ||
| 4820 | + OSSL_PARAM params[] = { | ||
| 4821 | + OSSL_PARAM_construct_utf8_string( | ||
| 4822 | + OSSL_MAC_PARAM_DIGEST, const_cast<char*>(md_name), 0), | ||
| 4823 | + OSSL_PARAM_construct_end(), | ||
| 4824 | + }; | ||
| 4825 | + | ||
| 4826 | + if (!ctx_.init(buf, params)) return false; | ||
| 4827 | + md_size_ = md.size(); | ||
| 4828 | + return true; | ||
| 4829 | + } | ||
| 4830 | + | ||
| 4831 | + bool HMACCtxPointer::update(const Buffer<const void>& buf) { | ||
| 4832 | + if (!ctx_) return false; | ||
| 4833 | + return ctx_.update(buf); | ||
| 4834 | + } | ||
| 4835 | + | ||
| 4836 | + DataPointer HMACCtxPointer::digest() { | ||
| 4837 | + if (md_size_ == 0) return {}; | ||
| 4838 | + auto data = DataPointer::Alloc(md_size_); | ||
| 4839 | + if (!data) return {}; | ||
| 4840 | + Buffer<void> buf = data; | ||
| 4841 | + if (!digestInto(&buf)) return {}; | ||
| 4842 | + return data.resize(buf.len); | ||
| 4843 | + } | ||
| 4844 | + | ||
| 4845 | + bool HMACCtxPointer::digestInto(Buffer<void>* buf) { | ||
| 4846 | + if (!ctx_) return false; | ||
| 4847 | + | ||
| 4848 | + size_t len = buf->len; | ||
| 4849 | + if (EVP_MAC_final( | ||
| 4850 | + ctx_.get(), static_cast<unsigned char*>(buf->data), &len, buf->len) != | ||
| 4851 | + 1) | ||
| 4852 | + return false; | ||
| 4853 | + | ||
| 4854 | + buf->len = len; | ||
| 4855 | + return true; | ||
| 4856 | + } | ||
| 4857 | + | ||
| 4858 | + HMACCtxPointer HMACCtxPointer::New() { | ||
| 4859 | + auto mac = EVPMacPointer::Fetch(OSSL_MAC_NAME_HMAC); | ||
| 4860 | + if (!mac) return {}; | ||
| 4861 | + | ||
| 4862 | + auto ctx = EVPMacCtxPointer::New(mac.get()); | ||
| 4863 | + if (!ctx) return {}; | ||
| 4864 | + | ||
| 4865 | + return HMACCtxPointer(std::move(mac), std::move(ctx)); | ||
| 4866 | + } | ||
| 4867 | + #endif // OPENSSL_WITH_EVP_MAC | ||
| 4781 | 4868 | ||
| 4782 | 4869 | DataPointer hashDigest(const Buffer<const unsigned char>& buf, | |
| 4783 | 4870 | const EVP_MD* md) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -65,9 +65,9 @@ | |||
| 65 | 65 | #endif | |
| 66 | 66 | ||
| 67 | 67 | #if OPENSSL_VERSION_PREREQ(3, 0) | |
| 68 | - #define OPENSSL_WITH_KMAC 1 | ||
| 68 | + #define OPENSSL_WITH_EVP_MAC 1 | ||
| 69 | 69 | #else | |
| 70 | - #define OPENSSL_WITH_KMAC 0 | ||
| 70 | + #define OPENSSL_WITH_EVP_MAC 0 | ||
| 71 | 71 | #endif | |
| 72 | 72 | ||
| 73 | 73 | #if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_PREREQ(3, 2) | |
@@ -1528,6 +1528,7 @@ class EVPMDCtxPointer final { | |||
| 1528 | 1528 | DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free> ctx_; | |
| 1529 | 1529 | }; | |
| 1530 | 1530 | ||
| 1531 | + #if !OPENSSL_WITH_EVP_MAC | ||
| 1531 | 1532 | class HMACCtxPointer final { | |
| 1532 | 1533 | public: | |
| 1533 | 1534 | HMACCtxPointer(); | |
@@ -1554,8 +1555,9 @@ class HMACCtxPointer final { | |||
| 1554 | 1555 | private: | |
| 1555 | 1556 | DeleteFnPtr<HMAC_CTX, HMAC_CTX_free> ctx_; | |
| 1556 | 1557 | }; | |
| 1558 | + #endif // !OPENSSL_WITH_EVP_MAC | ||
| 1557 | 1559 | ||
| 1558 | - #if OPENSSL_WITH_KMAC | ||
| 1560 | + #if OPENSSL_WITH_EVP_MAC | ||
| 1559 | 1561 | class EVPMacPointer final { | |
| 1560 | 1562 | public: | |
| 1561 | 1563 | EVPMacPointer() = default; | |
@@ -1603,7 +1605,34 @@ class EVPMacCtxPointer final { | |||
| 1603 | 1605 | private: | |
| 1604 | 1606 | DeleteFnPtr<EVP_MAC_CTX, EVP_MAC_CTX_free> ctx_; | |
| 1605 | 1607 | }; | |
| 1606 | - #endif // OPENSSL_WITH_KMAC | ||
| 1608 | + | ||
| 1609 | + class HMACCtxPointer final { | ||
| 1610 | + public: | ||
| 1611 | + HMACCtxPointer(); | ||
| 1612 | + HMACCtxPointer(HMACCtxPointer&& other) noexcept; | ||
| 1613 | + HMACCtxPointer& operator=(HMACCtxPointer&& other) noexcept; | ||
| 1614 | + NCRYPTO_DISALLOW_COPY(HMACCtxPointer) | ||
| 1615 | + ~HMACCtxPointer(); | ||
| 1616 | + | ||
| 1617 | + inline bool operator==(std::nullptr_t) noexcept { return ctx_ == nullptr; } | ||
| 1618 | + inline operator bool() const { return ctx_ != nullptr; } | ||
| 1619 | + void reset(); | ||
| 1620 | + | ||
| 1621 | + bool init(const Buffer<const void>& buf, const Digest& md); | ||
| 1622 | + bool update(const Buffer<const void>& buf); | ||
| 1623 | + DataPointer digest(); | ||
| 1624 | + bool digestInto(Buffer<void>* buf); | ||
| 1625 | + | ||
| 1626 | + static HMACCtxPointer New(); | ||
| 1627 | + | ||
| 1628 | + private: | ||
| 1629 | + HMACCtxPointer(EVPMacPointer&& mac, EVPMacCtxPointer&& ctx); | ||
| 1630 | + | ||
| 1631 | + EVPMacPointer mac_; | ||
| 1632 | + EVPMacCtxPointer ctx_; | ||
| 1633 | + size_t md_size_ = 0; | ||
| 1634 | + }; | ||
| 1635 | + #endif // OPENSSL_WITH_EVP_MAC | ||
| 1607 | 1636 | ||
| 1608 | 1637 | #ifndef OPENSSL_NO_ENGINE | |
| 1609 | 1638 | class EnginePointer final { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -90,12 +90,18 @@ using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>; | |||
| 90 | 90 | using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>; | |
| 91 | 91 | using DHPointer = DeleteFnPtr<DH, DH_free>; | |
| 92 | 92 | using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>; | |
| 93 | - using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>; | ||
| 94 | 93 | using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>; | |
| 95 | 94 | ``` | |
| 96 | 95 | ||
| 97 | 96 | Examples of these being used are pervasive through the `src/crypto` code. | |
| 98 | 97 | ||
| 98 | + `HMACCtxPointer` is a dedicated HMAC state wrapper rather than a plain | ||
| 99 | + `DeleteFnPtr` alias. On OpenSSL 3 and later it owns the provider-backed | ||
| 100 | + `EVP_MAC`/`EVP_MAC_CTX` state. On OpenSSL 1.1.1 and BoringSSL it owns the | ||
| 101 | + legacy `HMAC_CTX` state. HMAC call sites should use `HMACCtxPointer::New()`, | ||
| 102 | + `init()`, `update()`, and `digest()`/`digestInto()` so the backend selection | ||
| 103 | + stays contained in ncrypto. | ||
| 104 | + | ||
| 99 | 105 | ### `ByteSource` | |
| 100 | 106 | ||
| 101 | 107 | The `ByteSource` class is a helper utility representing a _read-only_ byte | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,9 +30,7 @@ using v8::Uint32; | |||
| 30 | 30 | using v8::Value; | |
| 31 | 31 | ||
| 32 | 32 | namespace crypto { | |
| 33 | - Hmac::Hmac(Environment* env, Local<Object> wrap) | ||
| 34 | - : BaseObject(env, wrap), | ||
| 35 | - ctx_(nullptr) { | ||
| 33 | + Hmac::Hmac(Environment* env, Local<Object> wrap) : BaseObject(env, wrap) { | ||
| 36 | 34 | MakeWeak(); | |
| 37 | 35 | } | |
| 38 | 36 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments