| ... | @@ -1031,14 +1031,18 @@ pub fn Modulus(comptime max_bits: comptime_int) type { | ... | @@ -1031,14 +1031,18 @@ pub fn Modulus(comptime max_bits: comptime_int) type { |
| 1031 | } | 1031 | } |
| 1032 | } | 1032 | } |
| 1033 | | 1033 | |
| | 1034 | const max_encoded_bytes = @divCeil(FeUint.capacity_bits, 8); |
| | 1035 | |
| 1034 | /// Returns x^e (mod m) in constant time. | 1036 | /// Returns x^e (mod m) in constant time. |
| 1035 | pub fn pow(self: Self, x: Fe, e: Fe) (NullExponentError || RepresentationError)!Fe { | 1037 | pub fn pow(self: Self, x: Fe, e: Fe) (NullExponentError || RepresentationError)!Fe { |
| 1036 | if (e.montgomery) { | 1038 | if (e.montgomery) { |
| 1037 | return error.UnexpectedRepresentation; | 1039 | return error.UnexpectedRepresentation; |
| 1038 | } | 1040 | } |
| 1039 | var buf: [Fe.encoded_bytes]u8 = undefined; | 1041 | |
| 1040 | e.toBytes(&buf, native_endian) catch unreachable; | 1042 | var buf: [max_encoded_bytes]u8 = undefined; |
| 1041 | return self.powWithEncodedExponent(x, &buf, native_endian); | 1043 | const len = self.encodedLen(); |
| | 1044 | e.toBytes(buf[0..len], native_endian) catch unreachable; |
| | 1045 | return self.powWithEncodedExponent(x, buf[0..len], native_endian); |
| 1042 | } | 1046 | } |
| 1043 | | 1047 | |
| 1044 | /// Returns x^e (mod m), assuming that the exponent is public. | 1048 | /// Returns x^e (mod m), assuming that the exponent is public. |
| ... | @@ -1047,12 +1051,9 @@ pub fn Modulus(comptime max_bits: comptime_int) type { | ... | @@ -1047,12 +1051,9 @@ pub fn Modulus(comptime max_bits: comptime_int) type { |
| 1047 | if (e.montgomery) { | 1051 | if (e.montgomery) { |
| 1048 | return error.UnexpectedRepresentation; | 1052 | return error.UnexpectedRepresentation; |
| 1049 | } | 1053 | } |
| 1050 | var e_normalized = Fe{ .v = e.v.normalize() }; | 1054 | var buf_: [max_encoded_bytes]u8 = undefined; |
| 1051 | var buf_: [Fe.encoded_bytes]u8 = undefined; | 1055 | const buf = buf_[0..@divCeil(e.v.bitLenPublic(), 8)]; |
| 1052 | var buf = buf_[0..@divCeil(e_normalized.v.limbs_len * t_bits, 8)]; | 1056 | e.toBytes(buf, .little) catch unreachable; |
| 1053 | e_normalized.toBytes(buf, .little) catch unreachable; | | |
| 1054 | const leading = @clz(e_normalized.v.limbsConst()[e_normalized.v.limbs_len - carry_bits]); | | |
| 1055 | buf = buf[0 .. buf.len - leading / 8]; | | |
| 1056 | return self.powWithEncodedPublicExponent(x, buf, .little); | 1057 | return self.powWithEncodedPublicExponent(x, buf, .little); |
| 1057 | } | 1058 | } |
| 1058 | | 1059 | |