From 9880d28a5efafec714679f52290541097dbb2b75 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Thu, 14 Jul 2022 13:56:12 +0800 Subject: [PATCH] Add serialization methods for Fp2, Fp6, Fp12 and Gt (#2) --- src/Neo.Cryptography.BLS12_381/Fp12.cs | 24 ++++++++++++++++++++++++ src/Neo.Cryptography.BLS12_381/Fp2.cs | 24 ++++++++++++++++++++++++ src/Neo.Cryptography.BLS12_381/Fp6.cs | 26 ++++++++++++++++++++++++++ src/Neo.Cryptography.BLS12_381/Gt.cs | 15 +++++++++++++++ 4 files changed, 89 insertions(+) diff --git a/src/Neo.Cryptography.BLS12_381/Fp12.cs b/src/Neo.Cryptography.BLS12_381/Fp12.cs index 4fb38ba..60ad044 100644 --- a/src/Neo.Cryptography.BLS12_381/Fp12.cs +++ b/src/Neo.Cryptography.BLS12_381/Fp12.cs @@ -44,6 +44,15 @@ public Fp12(in Fp6 c0, in Fp6 c1) C1 = c1; } + public static Fp12 FromBytes(ReadOnlySpan data) + { + if (data.Length != Size) + throw new FormatException($"The argument `{nameof(data)}` should contain {Size} bytes."); + Fp6 c0 = Fp6.FromBytes(data[Fp6.Size..]); + Fp6 c1 = Fp6.FromBytes(data[..Fp6.Size]); + return new(in c0, in c1); + } + public static bool operator ==(in Fp12 a, in Fp12 b) { return a.C0 == b.C0 & a.C1 == b.C1; @@ -70,6 +79,21 @@ public override int GetHashCode() return C0.GetHashCode() ^ C1.GetHashCode(); } + public byte[] ToArray() + { + byte[] result = GC.AllocateUninitializedArray(Size); + TryWrite(result); + return result; + } + + public bool TryWrite(Span buffer) + { + if (buffer.Length < Size) return false; + C0.TryWrite(buffer[Fp6.Size..Size]); + C1.TryWrite(buffer[0..Fp6.Size]); + return true; + } + public static Fp12 Random(RandomNumberGenerator rng) { return new(Fp6.Random(rng), Fp6.Random(rng)); diff --git a/src/Neo.Cryptography.BLS12_381/Fp2.cs b/src/Neo.Cryptography.BLS12_381/Fp2.cs index 49adf3e..8c318a5 100644 --- a/src/Neo.Cryptography.BLS12_381/Fp2.cs +++ b/src/Neo.Cryptography.BLS12_381/Fp2.cs @@ -35,6 +35,15 @@ public Fp2(in Fp c0, in Fp c1) C1 = c1; } + public static Fp2 FromBytes(ReadOnlySpan data) + { + if (data.Length != Size) + throw new FormatException($"The argument `{nameof(data)}` should contain {Size} bytes."); + Fp c0 = Fp.FromBytes(data[Fp.Size..]); + Fp c1 = Fp.FromBytes(data[..Fp.Size]); + return new(in c0, in c1); + } + public static Fp2 Random(RandomNumberGenerator rng) { return new(Fp.Random(rng), Fp.Random(rng)); @@ -66,6 +75,21 @@ public override int GetHashCode() return C0.GetHashCode() ^ C1.GetHashCode(); } + public byte[] ToArray() + { + byte[] result = GC.AllocateUninitializedArray(Size); + TryWrite(result); + return result; + } + + public bool TryWrite(Span buffer) + { + if (buffer.Length < Size) return false; + C0.TryWrite(buffer[Fp.Size..Size]); + C1.TryWrite(buffer[0..Fp.Size]); + return true; + } + public Fp2 FrobeniusMap() { // This is always just a conjugation. If you're curious why, here's diff --git a/src/Neo.Cryptography.BLS12_381/Fp6.cs b/src/Neo.Cryptography.BLS12_381/Fp6.cs index 0c54125..3261e30 100644 --- a/src/Neo.Cryptography.BLS12_381/Fp6.cs +++ b/src/Neo.Cryptography.BLS12_381/Fp6.cs @@ -42,6 +42,16 @@ public Fp6(in Fp2 c0, in Fp2 c1, in Fp2 c2) C2 = c2; } + public static Fp6 FromBytes(ReadOnlySpan data) + { + if (data.Length != Size) + throw new FormatException($"The argument `{nameof(data)}` should contain {Size} bytes."); + Fp2 c0 = Fp2.FromBytes(data[(Fp2.Size * 2)..]); + Fp2 c1 = Fp2.FromBytes(data[Fp2.Size..(Fp2.Size * 2)]); + Fp2 c2 = Fp2.FromBytes(data[..Fp2.Size]); + return new(in c0, in c1, in c2); + } + public static bool operator ==(in Fp6 a, in Fp6 b) { return a.C0 == b.C0 & a.C1 == b.C1 & a.C2 == b.C2; @@ -68,6 +78,22 @@ public override int GetHashCode() return C0.GetHashCode() ^ C1.GetHashCode() ^ C2.GetHashCode(); } + public byte[] ToArray() + { + byte[] result = GC.AllocateUninitializedArray(Size); + TryWrite(result); + return result; + } + + public bool TryWrite(Span buffer) + { + if (buffer.Length < Size) return false; + C0.TryWrite(buffer[(Fp2.Size * 2)..Size]); + C1.TryWrite(buffer[Fp2.Size..(Fp2.Size * 2)]); + C2.TryWrite(buffer[0..Fp2.Size]); + return true; + } + public static Fp6 Random(RandomNumberGenerator rng) { return new(Fp2.Random(rng), Fp2.Random(rng), Fp2.Random(rng)); diff --git a/src/Neo.Cryptography.BLS12_381/Gt.cs b/src/Neo.Cryptography.BLS12_381/Gt.cs index 38dd813..f0f3ce8 100644 --- a/src/Neo.Cryptography.BLS12_381/Gt.cs +++ b/src/Neo.Cryptography.BLS12_381/Gt.cs @@ -20,6 +20,11 @@ public Gt(in Fp12 f) Value = f; } + public static Gt FromBytes(ReadOnlySpan data) + { + return new(Fp12.FromBytes(data)); + } + public static bool operator ==(in Gt a, in Gt b) { return a.Value == b.Value; @@ -46,6 +51,16 @@ public override int GetHashCode() return Value.GetHashCode(); } + public byte[] ToArray() + { + return Value.ToArray(); + } + + public bool TryWrite(Span buffer) + { + return Value.TryWrite(buffer); + } + public static Gt Random(RandomNumberGenerator rng) { while (true)