Skip to content

Faster signatures #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Faster signatures #134

wants to merge 2 commits into from

Conversation

dchest
Copy link
Owner

@dchest dchest commented Nov 11, 2017

Use plain arrays instead of Float64Array.

This makes signing/verifying ~3 times faster.

On 2.6 GHz Intel Core i5 (MBPr Mid 2014), Node.js v8.8.1:

Before:

sign                                    92 ops           5.46 ms/op       183.17 ops/sec
sign.open                               48 ops          10.50 ms/op        95.26 ops/sec

After:

sign                                   269 ops           1.86 ms/op       536.52 ops/sec
sign.open                              136 ops           3.70 ms/op       270.55 ops/sec
@dchest dchest force-pushed the faster-signatures branch from f4ed5c0 to 328ee60 Compare December 9, 2017 13:31
@dchest
Copy link
Owner Author

dchest commented Mar 5, 2018

This potentially breaks constant timing. Arrays created by gf must be able to contain at least 44 bits, which is why Float64Array is used (JavaScript numbers, which are double/float64 can represent 2^53-bit integers). If we change it to Array, V8 will initially assume that these are 32-bit integers, which is why it performs faster. However, if multiplication pushes the number out of 32-bit range, V8 will have to convert the array to another representation, capable of representing more than 32-bit numbers (I assume, to doubles), thus producing a timing variation which depends on the number, which is secret data (in case of dh and signing, but not verifying).

This is just a theory, but it explains why I'm hesitant to merge this PR. I'd really like to do it, since it brings a great improvement in performance. Perhaps, someone more familiar with internals of JavaScript VMs can take a look?

linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 15, 2025
…riations introduced by previous solution (PR dchest#134) that could leak information about secret keys

PR makes:
signing ~2 times faster on m4 max (~ same performance as previous solution)
verifying ~40+ times faster (~20+ times faster than previous solution)

On M4 Max (MBP Nov 2024), Node.js v8.8.1:
linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 15, 2025
…riations introduced by previous solution (PR dchest#134) that could leak information about secret keys

PR makes:
signing ~2 times faster on m4 max (~ same performance as previous solution)
verifying ~40+ times faster (~20+ times faster than previous solution)

On M4 Max (MBP Nov 2024), tested in browser:

CURRENT
sign                                   405 ops           1.24 ms/op       809.68 ops/sec
sign.open                              206 ops           2.44 ms/op       410.44 ops/sec

PR dchest#134
sign                                   893 ops           0.56 ms/op      1784.93 ops/sec
sign.open                              456 ops           1.10 ms/op       910.36 ops/sec

THIS PR
sign                                   795 ops           0.63 ms/op      1589.36 ops/sec
sign.open                             8609 ops           0.06 ms/op     17193.93 ops/sec
linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 15, 2025
…aphic operations while maintaining security:

- **Eliminates timing variations** present in the previous solution (PR dchest#134) that could potentially leak secret key information
- **Signing operations:** ~2x faster on M4 Max compared to current implementation (slightly slower than PR dchest#134)
- **Verification operations:** ~40x faster than current implementation (~20x faster than previous PR dchest#134 solution)

On M4 Max (MBP Nov 2024), tested in Chrome Version 134.0.6998.89 - arm64:

| Operation | Operations | Time per operation | Operations per second | Delta |
|-----------|------------|--------------------|-----------------------|-------|
| sign      | 787 ops    | 0.64 ms/op        | 1573.69 ops/sec       | [+91.1%] |
| sign.open | 8641 ops   | 0.06 ms/op        | 17261.29 ops/sec      | [+4067.3%] |

| Operation | Operations | Time per operation | Operations per second | Delta |
|-----------|------------|--------------------|-----------------------|-------|
| sign      | 889 ops    | 0.56 ms/op        | 1775.51 ops/sec       | [+115.6%] |
| sign.open | 454 ops    | 1.10 ms/op        | 906.55 ops/sec        | [+118.9%] |

| Operation | Operations | Time per operation | Operations per second | Delta |
|-----------|------------|--------------------|-----------------------|-------|
| sign      | 412 ops    | 1.21 ms/op        | 823.34 ops/sec        | - |
| sign.open | 208 ops    | 2.41 ms/op        | 414.18 ops/sec        | - |
linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 15, 2025
…───────────┐

│                        PERFORMANCE IMPROVEMENTS SUMMARY                        │
├───────────────────────────────────────────────────────────────────────────────┤
│ This PR delivers significant performance improvements in cryptographic         │
│ operations while maintaining security:                                         │
│                                                                               │
│ • Eliminates timing variations present in the previous solution (PR dchest#134)      │
│   that could potentially leak secret key information                           │
│                                                                               │
│ • Signing operations: ~2x faster on M4 Max compared to current implementation  │
│   (slightly slower than PR dchest#134)                                               │
│                                                                               │
│ • Verification operations: ~40x faster than current implementation             │
│   (~20x faster than previous PR dchest#134 solution)                                 │
│                                                                               │
├───────────────────────────────────────────────────────────────────────────────┤
│                             BENCHMARK RESULTS                                  │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ On M4 Max (MBP Nov 2024), tested in Chrome Version 134.0.6998.89 - arm64:                   │
│                                                                                             │
│ THIS PR                                                                                     │
│ sign                 787 ops           0.64 ms/op      1573.69 ops/sec      [+91.1%]        │
│ sign.open           8641 ops           0.06 ms/op     17261.29 ops/sec      [+4067.3%]      │
│                                                                                             │
│ PR dchest#134 with risk of timing attacks                                                         │
│ sign                 889 ops           0.56 ms/op      1775.51 ops/sec      [+115.6%]       │
│ sign.open            454 ops           1.10 ms/op       906.55 ops/sec      [+118.9%]       │
│                                                                                             │
│ CURRENT IMPLEMENTATION                                                                      │
│ sign                 412 ops           1.21 ms/op       823.34 ops/sec      -               │
│ sign.open            208 ops           2.41 ms/op       414.18 ops/sec      -               │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 15, 2025
Huge increase of performance in signing/verifying WITHOUT timing variations that could leak information about secret keys (that made PR dchest#134 unmergeable)

┌───────────────────────────────────────────────────────────────────────────────┐
│                        PERFORMANCE IMPROVEMENTS SUMMARY                        │
├───────────────────────────────────────────────────────────────────────────────┤
│ • Signing: ~2x faster on M4 Max compared to current implementation             │
│   (slightly slower than previous solution)                                     │
│                                                                               │
│ • Verification: ~40x faster than current implementation                        │
│   (~20x faster than previous PR dchest#134 solution)                                 │
│                                                                               │
├───────────────────────────────────────────────────────────────────────────────┤
│                             BENCHMARK RESULTS                                  │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ On M4 Max (MBP Nov 2024), tested in Chrome Version 134.0.6998.89 - arm64:                   │
│                                                                                             │
│ THIS PR                                                                                     │
│ sign                 787 ops           0.64 ms/op      1573.69 ops/sec      [+91.1%]        │
│ sign.open           8641 ops           0.06 ms/op     17261.29 ops/sec      [+4067.3%]      │
│                                                                                             │
│ PR dchest#134 with risk of timing attacks                                                         │
│ sign                 889 ops           0.56 ms/op      1775.51 ops/sec      [+115.6%]       │
│ sign.open            454 ops           1.10 ms/op       906.55 ops/sec      [+118.9%]       │
│                                                                                             │
│ CURRENT IMPLEMENTATION                                                                      │
│ sign                 412 ops           1.21 ms/op       823.34 ops/sec      -               │
│ sign.open            208 ops           2.41 ms/op       414.18 ops/sec      -               │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
linegel pushed a commit to linegel/tweetnacl-js that referenced this pull request Mar 16, 2025
Huge increase of performance in signing/verifying WITHOUT timing variations that could leak information about secret keys (that made PR dchest#134 unmergeable)

┌───────────────────────────────────────────────────────────────────────────────┐
│                        PERFORMANCE IMPROVEMENTS SUMMARY                        │
├───────────────────────────────────────────────────────────────────────────────┤
│ • Signing: ~2x faster on M4 Max compared to current implementation             │
│   (slightly slower than previous solution)                                     │
│                                                                               │
│ • Verification: ~40x faster than current implementation                        │
│   (~20x faster than previous PR dchest#134 solution)                                 │
│                                                                               │
├───────────────────────────────────────────────────────────────────────────────┤
│                             BENCHMARK RESULTS                                  │
├─────────────────────────────────────────────────────────────────────────────────────────────┤
│ On M4 Max (MBP Nov 2024), tested in Chrome Version 134.0.6998.89 - arm64:                   │
│                                                                                             │
│ THIS PR                                                                                     │
│ sign                 787 ops           0.64 ms/op      1573.69 ops/sec      [+91.1%]        │
│ sign.open           8641 ops           0.06 ms/op     17261.29 ops/sec      [+4067.3%]      │
│                                                                                             │
│ PR dchest#134 with risk of timing attacks                                                         │
│ sign                 889 ops           0.56 ms/op      1775.51 ops/sec      [+115.6%]       │
│ sign.open            454 ops           1.10 ms/op       906.55 ops/sec      [+118.9%]       │
│                                                                                             │
│ CURRENT IMPLEMENTATION                                                                      │
│ sign                 412 ops           1.21 ms/op       823.34 ops/sec      -               │
│ sign.open            208 ops           2.41 ms/op       414.18 ops/sec      -               │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant