| 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 | 108 | h.final(&hram64); |
| 109 | 109 | const hram = Curve.scalar.reduce64(hram64); |
| 110 | 110 | |
| 111 | const ah = try a.neg().mul(hram); | |
| 112 | const sb_ah = (try Curve.basePoint.mul(s.*)).add(ah); | |
| 111 | const ah = try a.neg().mulPublic(hram); | |
| 112 | const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); | |
| 113 | 113 | if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { |
| 114 | 114 | return error.InvalidSignature; |
| 115 | 115 | } else |_| {} |
| ... | ... | @@ -170,18 +170,18 @@ pub const Ed25519 = struct { |
| 170 | 170 | |
| 171 | 171 | var zr = Curve.neutralElement; |
| 172 | 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 | 175 | zr = zr.clearCofactor(); |
| 176 | 176 | |
| 177 | 177 | var zah = Curve.neutralElement; |
| 178 | 178 | for (z_batch) |z, i| { |
| 179 | 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 | 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 | 185 | if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { |
| 186 | 186 | return error.InvalidSignature; |
| 187 | 187 | } else |_| {} |
lib/std/crypto/25519/edwards25519.zig+23-3| ... | ... | @@ -149,13 +149,19 @@ pub const Edwards25519 = struct { |
| 149 | 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 | 153 | var q = Edwards25519.identityElement; |
| 154 | 154 | var pos: usize = 252; |
| 155 | 155 | while (true) : (pos -= 4) { |
| 156 | 156 | q = q.dbl().dbl().dbl().dbl(); |
| 157 | 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 | 165 | if (pos == 0) break; |
| 160 | 166 | } |
| 161 | 167 | try q.rejectIdentity(); |
| ... | ... | @@ -185,7 +191,21 @@ pub const Edwards25519 = struct { |
| 185 | 191 | pc = precompute(p); |
| 186 | 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 | 211 | /// Multiply an Edwards25519 point by a scalar after "clamping" it. |