[#1] Define SDK structure
TODO: Вынести маппинг модель -> grpc в отдельный слой Signed-off-by: Ivan Pchelintsev <i.pchelintsev@yadro.com>
This commit is contained in:
parent
905f683bf1
commit
2800fff041
57 changed files with 5760 additions and 0 deletions
254
sdk/src/FrostFS.SDK.Cryptography/Tz/GF127.cs
Normal file
254
sdk/src/FrostFS.SDK.Cryptography/Tz/GF127.cs
Normal file
|
@ -0,0 +1,254 @@
|
|||
using System.Security.Cryptography;
|
||||
|
||||
namespace FrostFS.SDK.Cryptography.Tz
|
||||
{
|
||||
// GF127 represents element of GF(2^127)
|
||||
public class GF127 : IEquatable<GF127>
|
||||
{
|
||||
public const int ByteSize = 16;
|
||||
public const ulong MaxUlong = ulong.MaxValue;
|
||||
public const ulong MSB64 = (ulong)1 << 63; // 2^63
|
||||
public static readonly GF127 Zero = new(0, 0);
|
||||
public static readonly GF127 One = new(1, 0);
|
||||
public static readonly GF127 X127X631 = new(MSB64 + 1, MSB64); // x^127+x^63+1
|
||||
|
||||
private readonly ulong[] _data;
|
||||
|
||||
public ulong this[int index]
|
||||
{
|
||||
get { return _data[index]; }
|
||||
set { _data[index] = value; }
|
||||
}
|
||||
|
||||
public GF127(ulong[] value)
|
||||
{
|
||||
if (value is null || value.Length != 2)
|
||||
throw new ArgumentException(nameof(value) + "is invalid");
|
||||
_data = value;
|
||||
}
|
||||
|
||||
// Constructs new element of GF(2^127) as u1*x^64 + u0.
|
||||
// It is assumed that u1 has zero MSB.
|
||||
public GF127(ulong u0, ulong u1) : this(new ulong[] { u0, u1 })
|
||||
{
|
||||
}
|
||||
|
||||
public GF127() : this(0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is null)
|
||||
return false;
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
if (obj is GF127 b)
|
||||
return Equals(b);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this[0].GetHashCode() + this[1].GetHashCode();
|
||||
}
|
||||
|
||||
public bool Equals(GF127 other)
|
||||
{
|
||||
if (other is null)
|
||||
return false;
|
||||
if (ReferenceEquals(this, other))
|
||||
return true;
|
||||
return this[0] == other[0] && this[1] == other[1];
|
||||
}
|
||||
|
||||
// return the index of MSB
|
||||
private int IndexOfMSB()
|
||||
{
|
||||
int i = Helper.GetLeadingZeros(this[1]);
|
||||
if (i == 64)
|
||||
i += Helper.GetLeadingZeros(this[0]);
|
||||
return 127 - i;
|
||||
}
|
||||
|
||||
// Set index n to 1
|
||||
public static GF127 SetN(int n)
|
||||
{
|
||||
if (n < 64)
|
||||
return new GF127((ulong)1 << n, 0);
|
||||
return new GF127(0, (ulong)1 << (n - 64));
|
||||
}
|
||||
|
||||
// Add
|
||||
public static GF127 operator +(GF127 a, GF127 b)
|
||||
{
|
||||
return new GF127(a[0] ^ b[0], a[1] ^ b[1]);
|
||||
}
|
||||
|
||||
// Bitwise-and
|
||||
public static GF127 operator &(GF127 a, GF127 b)
|
||||
{
|
||||
return new GF127(a[0] & b[0], a[1] & b[1]);
|
||||
}
|
||||
|
||||
// Multiply
|
||||
public static GF127 operator *(GF127 a, GF127 b) // 2^63 * 2, 10
|
||||
{
|
||||
GF127 r = new();
|
||||
GF127 c = a;
|
||||
|
||||
if (b[1] == 0)
|
||||
{
|
||||
for (int i = 0; i < b[0].GetNonZeroLength(); i++)
|
||||
{
|
||||
if ((b[0] & ((ulong)1 << i)) != 0)
|
||||
r += c;
|
||||
c = Mul10(c); // c = c * 2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
if ((b[0] & ((ulong)1 << i)) != 0)
|
||||
r += c;
|
||||
c = Mul10(c); // c = c * 2
|
||||
}
|
||||
|
||||
for (int i = 0; i < b[1].GetNonZeroLength(); i++)
|
||||
{
|
||||
if ((b[1] & ((ulong)1 << i)) != 0)
|
||||
r += c;
|
||||
c = Mul10(c);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Inverse, returns a^-1
|
||||
// Extended Euclidean Algorithm
|
||||
// https://link.springer.com/content/pdf/10.1007/3-540-44499-8_1.pdf
|
||||
public static GF127 Inv(GF127 a)
|
||||
{
|
||||
GF127 v = X127X631,
|
||||
u = a,
|
||||
c = new(1, 0),
|
||||
d = new(0, 0),
|
||||
t,
|
||||
x;
|
||||
|
||||
int du = u.IndexOfMSB();
|
||||
int dv = v.IndexOfMSB();
|
||||
// degree of polynomial is a position of most significant bit
|
||||
while (du != 0)
|
||||
{
|
||||
if (du < dv)
|
||||
{
|
||||
(v, u) = (u, v);
|
||||
(dv, du) = (du, dv);
|
||||
(d, c) = (c, d);
|
||||
}
|
||||
|
||||
x = SetN(du - dv);
|
||||
t = x * v;
|
||||
u += t;
|
||||
// because * performs reduction on t, manually reduce u at first step
|
||||
if (u.IndexOfMSB() == 127)
|
||||
u += X127X631;
|
||||
|
||||
t = x * d;
|
||||
c += t;
|
||||
|
||||
du = u.IndexOfMSB();
|
||||
dv = v.IndexOfMSB();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// Mul10 returns a*x
|
||||
public static GF127 Mul10(GF127 a)
|
||||
{
|
||||
GF127 b = new();
|
||||
var c = (a[0] & MSB64) >> 63;
|
||||
b[0] = a[0] << 1;
|
||||
b[1] = (a[1] << 1) ^ c;
|
||||
if ((b[1] & MSB64) != 0)
|
||||
{
|
||||
b[0] ^= X127X631[0];
|
||||
b[1] ^= X127X631[1];
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
// Mul11 returns a*(x+1)
|
||||
public static GF127 Mul11(GF127 a)
|
||||
{
|
||||
GF127 b = new();
|
||||
var c = (a[0] & MSB64) >> 63;
|
||||
b[0] = a[0] ^ (a[0] << 1);
|
||||
b[1] = a[1] ^ (a[1] << 1) ^ c;
|
||||
if ((b[1] & MSB64) == 0) return b;
|
||||
b[0] ^= X127X631[0];
|
||||
b[1] ^= X127X631[1];
|
||||
return b;
|
||||
}
|
||||
|
||||
// Random returns random element from GF(2^127).
|
||||
// Is used mostly for testing.
|
||||
public static GF127 Random()
|
||||
{
|
||||
using RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||
return new GF127(rng.NextUlong(), rng.NextUlong() >> 1);
|
||||
}
|
||||
|
||||
// FromByteArray does the deserialization stuff
|
||||
public GF127 FromByteArray(byte[] data)
|
||||
{
|
||||
if (data.Length != ByteSize)
|
||||
throw new ArgumentException(
|
||||
nameof(data) + $" wrong data lenght, {nameof(GF127)} expect={ByteSize}, actual={data.Length}"
|
||||
);
|
||||
var t0 = new byte[8];
|
||||
var t1 = new byte[8];
|
||||
Array.Copy(data, 0, t1, 0, 8);
|
||||
Array.Copy(data, 8, t0, 0, 8);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(t0);
|
||||
Array.Reverse(t1);
|
||||
}
|
||||
|
||||
_data[0] = BitConverter.ToUInt64(t0);
|
||||
_data[1] = BitConverter.ToUInt64(t1);
|
||||
if ((_data[1] & MSB64) != 0)
|
||||
throw new ArgumentException(nameof(data) + " invalid data");
|
||||
return this;
|
||||
}
|
||||
|
||||
// ToArray() represents element of GF(2^127) as byte array of length 16.
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
var buff = new byte[16];
|
||||
var b0 = BitConverter.GetBytes(_data[0]);
|
||||
var b1 = BitConverter.GetBytes(_data[1]);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(b0);
|
||||
Array.Reverse(b1);
|
||||
}
|
||||
|
||||
Array.Copy(b1, 0, buff, 0, 8);
|
||||
Array.Copy(b0, 0, buff, 8, 8);
|
||||
return buff;
|
||||
}
|
||||
|
||||
// ToString() returns hex-encoded representation, starting with MSB.
|
||||
public override string ToString()
|
||||
{
|
||||
return Convert.ToHexString(ToByteArray());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue