| author | |
| committer | |
| log | 0fb6fdd7eb8c9ec7057e2ecb2d0d4506cddc6dd1 |
| tree | f88547541eded0d3c924956e7cf9dcededdb64c7 |
| parent | ff658abe790890c3f4e6f7fee34e52da4755a93c |
This is useful to save some CPU cycles when the scalar is public,
such as when verifying signatures.2 files changed, 28 insertions(+), 8 deletions(-)
lib/std/crypto/25519/ed25519.zig+5-5| ... | @@ -108,8 +108,8 @@ pub const Ed25519 = struct { | ... | @@ -108,8 +108,8 @@ pub const Ed25519 = struct { |
| 108 | h.final(&hram64); | 108 | h.final(&hram64); |
| 109 | const hram = Curve.scalar.reduce64(hram64); | 109 | const hram = Curve.scalar.reduce64(hram64); |
| 110 | 110 | ||
| 111 | const ah = try a.neg().mul(hram); | 111 | const ah = try a.neg().mulPublic(hram); |
| 112 | const sb_ah = (try Curve.basePoint.mul(s.*)).add(ah); | 112 | const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); |
| 113 | if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { | 113 | if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { |
| 114 | return error.InvalidSignature; | 114 | return error.InvalidSignature; |
| 115 | } else |_| {} | 115 | } else |_| {} |
| ... | @@ -170,18 +170,18 @@ pub const Ed25519 = struct { | ... | @@ -170,18 +170,18 @@ pub const Ed25519 = struct { |
| 170 | 170 | ||
| 171 | var zr = Curve.neutralElement; | 171 | var zr = Curve.neutralElement; |
| 172 | for (z_batch) |z, i| { | 172 | for (z_batch) |z, i| { |
| 173 | zr = zr.add(try expected_r_batch[i].mul(z)); | 173 | zr = zr.add(try expected_r_batch[i].mulPublic(z)); |
| 174 | } | 174 | } |
| 175 | zr = zr.clearCofactor(); | 175 | zr = zr.clearCofactor(); |
| 176 | 176 | ||
| 177 | var zah = Curve.neutralElement; | 177 | var zah = Curve.neutralElement; |
| 178 | for (z_batch) |z, i| { | 178 | for (z_batch) |z, i| { |
| 179 | const zh = Curve.scalar.mul(z, hram_batch[i]); | 179 | const zh = Curve.scalar.mul(z, hram_batch[i]); |
| 180 | zah = zah.add(try a_batch[i].mul(zh)); | 180 | zah = zah.add(try a_batch[i].mulPublic(zh)); |
| 181 | } | 181 | } |
| 182 | zah = zah.clearCofactor(); | 182 | zah = zah.clearCofactor(); |
| 183 | 183 | ||
| 184 | const zsb = try Curve.basePoint.mul(zs_sum); | 184 | const zsb = try Curve.basePoint.mulPublic(zs_sum); |
| 185 | if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { | 185 | if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { |
| 186 | return error.InvalidSignature; | 186 | return error.InvalidSignature; |
| 187 | } else |_| {} | 187 | } else |_| {} |
lib/std/crypto/25519/edwards25519.zig+23-3| ... | @@ -149,13 +149,19 @@ pub const Edwards25519 = struct { | ... | @@ -149,13 +149,19 @@ pub const Edwards25519 = struct { |
| 149 | return t; | 149 | return t; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | fn pcMul(pc: [16]Edwards25519, s: [32]u8) !Edwards25519 { | 152 | fn pcMul(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { |
| 153 | var q = Edwards25519.identityElement; | 153 | var q = Edwards25519.identityElement; |
| 154 | var pos: usize = 252; | 154 | var pos: usize = 252; |
| 155 | while (true) : (pos -= 4) { | 155 | while (true) : (pos -= 4) { |
| 156 | q = q.dbl().dbl().dbl().dbl(); | 156 | q = q.dbl().dbl().dbl().dbl(); |
| 157 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; | 157 | const bit = (s[pos >> 3] >> @truncate(u3, pos)) & 0xf; |
| 158 | q = q.add(pcSelect(pc, bit)); | 158 | if (vartime) { |
| 159 | if (bit != 0) { | ||
| 160 | q = q.add(pc[bit]); | ||
| 161 | } | ||
| 162 | } else { | ||
| 163 | q = q.add(pcSelect(pc, bit)); | ||
| 164 | } | ||
| 159 | if (pos == 0) break; | 165 | if (pos == 0) break; |
| 160 | } | 166 | } |
| 161 | try q.rejectIdentity(); | 167 | try q.rejectIdentity(); |
| ... | @@ -185,7 +191,21 @@ pub const Edwards25519 = struct { | ... | @@ -185,7 +191,21 @@ pub const Edwards25519 = struct { |
| 185 | pc = precompute(p); | 191 | pc = precompute(p); |
| 186 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; | 192 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| 187 | } | 193 | } |
| 188 | return pcMul(pc, s); | 194 | return pcMul(pc, s, false); |
| 195 | } | ||
| 196 | |||
| 197 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* | ||
| 198 | /// This can be used for signature verification. | ||
| 199 | pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { | ||
| 200 | var pc: [16]Edwards25519 = undefined; | ||
| 201 | if (p.is_base) { | ||
| 202 | @setEvalBranchQuota(10000); | ||
| 203 | pc = comptime precompute(Edwards25519.basePoint); | ||
| 204 | } else { | ||
| 205 | pc = precompute(p); | ||
| 206 | pc[4].rejectIdentity() catch |_| return error.WeakPublicKey; | ||
| 207 | } | ||
| 208 | return pcMul(pc, s, true); | ||
| 189 | } | 209 | } |
| 190 | 210 | ||
| 191 | /// Multiply an Edwards25519 point by a scalar after "clamping" it. | 211 | /// Multiply an Edwards25519 point by a scalar after "clamping" it. |