| ... | @@ -4,10 +4,8 @@ const mem = std.mem; | ... | @@ -4,10 +4,8 @@ const mem = std.mem; |
| 4 | | 4 | |
| 5 | const NonCanonicalError = std.crypto.errors.NonCanonicalError; | 5 | const NonCanonicalError = std.crypto.errors.NonCanonicalError; |
| 6 | | 6 | |
| 7 | /// 2^252 + 27742317777372353535851937790883648493 | 7 | /// The scalar field order. |
| 8 | pub const field_size = [32]u8{ | 8 | pub const field_order: u256 = 7237005577332262213973186563042994240857116359379907606001950938285454250989; |
| 9 | 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // 2^252+27742317777372353535851937790883648493 | | |
| 10 | }; | | |
| 11 | | 9 | |
| 12 | /// A compressed scalar | 10 | /// A compressed scalar |
| 13 | pub const CompressedScalar = [32]u8; | 11 | pub const CompressedScalar = [32]u8; |
| ... | @@ -15,6 +13,12 @@ pub const CompressedScalar = [32]u8; | ... | @@ -15,6 +13,12 @@ pub const CompressedScalar = [32]u8; |
| 15 | /// Zero | 13 | /// Zero |
| 16 | pub const zero = [_]u8{0} ** 32; | 14 | pub const zero = [_]u8{0} ** 32; |
| 17 | | 15 | |
| | 16 | const field_order_s = s: { |
| | 17 | var s: [32]u8 = undefined; |
| | 18 | mem.writeIntLittle(u256, &s, field_order); |
| | 19 | break :s s; |
| | 20 | }; |
| | 21 | |
| 18 | /// Reject a scalar whose encoding is not canonical. | 22 | /// Reject a scalar whose encoding is not canonical. |
| 19 | pub fn rejectNonCanonical(s: CompressedScalar) NonCanonicalError!void { | 23 | pub fn rejectNonCanonical(s: CompressedScalar) NonCanonicalError!void { |
| 20 | var c: u8 = 0; | 24 | var c: u8 = 0; |
| ... | @@ -22,9 +26,9 @@ pub fn rejectNonCanonical(s: CompressedScalar) NonCanonicalError!void { | ... | @@ -22,9 +26,9 @@ pub fn rejectNonCanonical(s: CompressedScalar) NonCanonicalError!void { |
| 22 | var i: usize = 31; | 26 | var i: usize = 31; |
| 23 | while (true) : (i -= 1) { | 27 | while (true) : (i -= 1) { |
| 24 | const xs = @as(u16, s[i]); | 28 | const xs = @as(u16, s[i]); |
| 25 | const xfield_size = @as(u16, field_size[i]); | 29 | const xfield_order_s = @as(u16, field_order_s[i]); |
| 26 | c |= @intCast(u8, ((xs -% xfield_size) >> 8) & n); | 30 | c |= @intCast(u8, ((xs -% xfield_order_s) >> 8) & n); |
| 27 | n &= @intCast(u8, ((xs ^ xfield_size) -% 1) >> 8); | 31 | n &= @intCast(u8, ((xs ^ xfield_order_s) -% 1) >> 8); |
| 28 | if (i == 0) break; | 32 | if (i == 0) break; |
| 29 | } | 33 | } |
| 30 | if (c == 0) { | 34 | if (c == 0) { |
| ... | @@ -77,7 +81,7 @@ pub fn add(a: CompressedScalar, b: CompressedScalar) CompressedScalar { | ... | @@ -77,7 +81,7 @@ pub fn add(a: CompressedScalar, b: CompressedScalar) CompressedScalar { |
| 77 | | 81 | |
| 78 | /// Return -s (mod L) | 82 | /// Return -s (mod L) |
| 79 | pub fn neg(s: CompressedScalar) CompressedScalar { | 83 | pub fn neg(s: CompressedScalar) CompressedScalar { |
| 80 | const fs: [64]u8 = field_size ++ [_]u8{0} ** 32; | 84 | const fs: [64]u8 = field_order_s ++ [_]u8{0} ** 32; |
| 81 | var sx: [64]u8 = undefined; | 85 | var sx: [64]u8 = undefined; |
| 82 | mem.copy(u8, sx[0..32], s[0..]); | 86 | mem.copy(u8, sx[0..32], s[0..]); |
| 83 | mem.set(u8, sx[32..], 0); | 87 | mem.set(u8, sx[32..], 0); |
| ... | @@ -848,7 +852,7 @@ test "scalar25519" { | ... | @@ -848,7 +852,7 @@ test "scalar25519" { |
| 848 | var buf: [128]u8 = undefined; | 852 | var buf: [128]u8 = undefined; |
| 849 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&y)}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F"); | 853 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&y)}), "1E979B917937F3DE71D18077F961F6CEFF01030405060708010203040506070F"); |
| 850 | | 854 | |
| 851 | const reduced = reduce(field_size); | 855 | const reduced = reduce(field_order_s); |
| 852 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&reduced)}), "0000000000000000000000000000000000000000000000000000000000000000"); | 856 | try std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&reduced)}), "0000000000000000000000000000000000000000000000000000000000000000"); |
| 853 | } | 857 | } |
| 854 | | 858 | |
| ... | @@ -881,7 +885,7 @@ test "random scalar" { | ... | @@ -881,7 +885,7 @@ test "random scalar" { |
| 881 | } | 885 | } |
| 882 | | 886 | |
| 883 | test "64-bit reduction" { | 887 | test "64-bit reduction" { |
| 884 | const bytes = field_size ++ [_]u8{0} ** 32; | 888 | const bytes = field_order_s ++ [_]u8{0} ** 32; |
| 885 | const x = Scalar.fromBytes64(bytes); | 889 | const x = Scalar.fromBytes64(bytes); |
| 886 | try std.testing.expect(x.isZero()); | 890 | try std.testing.expect(x.isZero()); |
| 887 | } | 891 | } |