diff options
| author | Frank Denis <github@pureftpd.org> | 2020-10-19 21:39:09 +0200 |
|---|---|---|
| committer | Frank Denis <github@pureftpd.org> | 2020-10-22 09:58:26 +0200 |
| commit | 0fb6fdd7eb8c9ec7057e2ecb2d0d4506cddc6dd1 (patch) | |
| tree | f88547541eded0d3c924956e7cf9dcededdb64c7 /lib/std | |
| parent | ff658abe790890c3f4e6f7fee34e52da4755a93c (diff) | |
| download | zig-0fb6fdd7eb8c9ec7057e2ecb2d0d4506cddc6dd1.tar.gz zig-0fb6fdd7eb8c9ec7057e2ecb2d0d4506cddc6dd1.zip | |
Support variable-time edwards25519 scalar multiplication
This is useful to save some CPU cycles when the scalar is public,
such as when verifying signatures.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/crypto/25519/ed25519.zig | 10 | ||||
| -rw-r--r-- | lib/std/crypto/25519/edwards25519.zig | 26 |
2 files changed, 28 insertions, 8 deletions
diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index e7df807cd3..1a739de5c6 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -108,8 +108,8 @@ pub const Ed25519 = struct { h.final(&hram64); const hram = Curve.scalar.reduce64(hram64); - const ah = try a.neg().mul(hram); - const sb_ah = (try Curve.basePoint.mul(s.*)).add(ah); + const ah = try a.neg().mulPublic(hram); + const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { return error.InvalidSignature; } else |_| {} @@ -170,18 +170,18 @@ pub const Ed25519 = struct { var zr = Curve.neutralElement; for (z_batch) |z, i| { - zr = zr.add(try expected_r_batch[i].mul(z)); + zr = zr.add(try expected_r_batch[i].mulPublic(z)); } zr = zr.clearCofactor(); var zah = Curve.neutralElement; for (z_batch) |z, i| { const zh = Curve.scalar.mul(z, hram_batch[i]); - zah = zah.add(try a_batch[i].mul(zh)); + zah = zah.add(try a_batch[i].mulPublic(zh)); } zah = zah.clearCofactor(); - const zsb = try Curve.basePoint.mul(zs_sum); + const zsb = try Curve.basePoint.mulPublic(zs_sum); if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { return error.InvalidSignature; } else |_| {} diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index 7f85fc492a..a8991ac518 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -149,13 +149,19 @@ pub const Edwards25519 = struct { return t; } - fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 { + fn pcMul(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { var q = Edwards25519.identityElement; var pos: usize = 252; while (true) : (pos -= 4) { q = q.dbl().dbl().dbl().dbl(); const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; - q = q.add(pcSelect(pc, bit)); + if (vartime) { + if (bit != 0) { + q = q.add(pc[bit]); + } + } else { + q = q.add(pcSelect(pc, bit)); + } if (pos == 0) break; } try q.rejectIdentity(); @@ -185,7 +191,21 @@ pub const Edwards25519 = struct { pc = precompute(p); pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; } - return pcMul(pc, s); + return pcMul(pc, s, false); + } + + /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* + /// This can be used for signature verification. + pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { + var pc: [16]Edwards25519 = undefined; + if (p.is_base) { + @setEvalBranchQuota(10000); + pc = comptime precompute(Edwards25519.basePoint); + } else { + pc = precompute(p); + pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; + } + return pcMul(pc, s, true); } /// Multiply an Edwards25519 point by a scalar after "clamping" it. |
