diff --git a/.gitignore b/.gitignore index 5659307..cf6e05a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.dll *.so *.dylib +*.pdb # Test binary, built with `go test -c` *.test @@ -31,3 +32,4 @@ antlr-*.jar # binary bin/ release/ +obj/ diff --git a/FrostFS.SDK.sln b/FrostFS.SDK.sln index 37b7f76..d7d789e 100644 --- a/FrostFS.SDK.sln +++ b/FrostFS.SDK.sln @@ -1,12 +1,11 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{A087047E-2505-4137-97CC-689A5AD58A0C}" +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ClientV2", "src\FrostFS.SDK.ClientV2\FrostFS.SDK.ClientV2.csproj", "{F9CE6347-111A-4CE6-8BB2-545469838F47}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{3D804F4A-B0B2-47A5-B006-BE447BE64B50}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.Cryptography", "src\FrostFS.SDK.Cryptography\FrostFS.SDK.Cryptography.csproj", "{599E2FF8-12C0-414D-B295-4C971A0A1A63}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ModelsV2", "src\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj", "{14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrostFS.SDK.ModelsV2", "src\FrostFS.SDK.ModelsV2\FrostFS.SDK.ModelsV2.csproj", "{3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostFS.SDK.ProtosV2", "src\FrostFS.SDK.ProtosV2\FrostFS.SDK.ProtosV2.csproj", "{5012EF96-9C9E-4E77-BC78-B4111EE54107}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -14,25 +13,25 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A087047E-2505-4137-97CC-689A5AD58A0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A087047E-2505-4137-97CC-689A5AD58A0C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A087047E-2505-4137-97CC-689A5AD58A0C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A087047E-2505-4137-97CC-689A5AD58A0C}.Release|Any CPU.Build.0 = Release|Any CPU - {F9CE6347-111A-4CE6-8BB2-545469838F47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F9CE6347-111A-4CE6-8BB2-545469838F47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F9CE6347-111A-4CE6-8BB2-545469838F47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F9CE6347-111A-4CE6-8BB2-545469838F47}.Release|Any CPU.Build.0 = Release|Any CPU - {B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B04EBDF5-A446-49D6-B1D7-7D729D94E8E0}.Release|Any CPU.Build.0 = Release|Any CPU - {599E2FF8-12C0-414D-B295-4C971A0A1A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {599E2FF8-12C0-414D-B295-4C971A0A1A63}.Debug|Any CPU.Build.0 = Debug|Any CPU - {599E2FF8-12C0-414D-B295-4C971A0A1A63}.Release|Any CPU.ActiveCfg = Release|Any CPU - {599E2FF8-12C0-414D-B295-4C971A0A1A63}.Release|Any CPU.Build.0 = Release|Any CPU - {3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3F6E5EE6-2AAC-45BE-A5E2-B83D11F90CC3}.Release|Any CPU.Build.0 = Release|Any CPU + {50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50D8F61F-C302-4AC9-8D8A-AB0B8C0988C3}.Release|Any CPU.Build.0 = Release|Any CPU + {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D804F4A-B0B2-47A5-B006-BE447BE64B50}.Release|Any CPU.Build.0 = Release|Any CPU + {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14DC8AC7-E310-40C2-ACDF-5BE78FC0E1B2}.Release|Any CPU.Build.0 = Release|Any CPU + {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5012EF96-9C9E-4E77-BC78-B4111EE54107}.Release|Any CPU.Build.0 = Release|Any CPU + {B738F3E1-654D-41A3-B068-58ED122BB688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B738F3E1-654D-41A3-B068-58ED122BB688}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B738F3E1-654D-41A3-B068-58ED122BB688}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B738F3E1-654D-41A3-B068-58ED122BB688}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/FrostFS.SDK.ClientV2/Client.cs b/src/FrostFS.SDK.ClientV2/Client.cs index 2c0bc15..7cb47d6 100644 --- a/src/FrostFS.SDK.ClientV2/Client.cs +++ b/src/FrostFS.SDK.ClientV2/Client.cs @@ -1,3 +1,4 @@ +using System; using System.Security.Cryptography; using FrostFS.Container; using FrostFS.Netmap; @@ -14,15 +15,15 @@ namespace FrostFS.SDK.ClientV2; public partial class Client: IFrostFSClient { - private GrpcChannel _channel; + private GrpcChannel? _channel; private readonly ECDsa _key; public readonly OwnerId OwnerId; - public readonly Version Version = new (2, 13); + public readonly Version Version = new(2, 13); - private ContainerService.ContainerServiceClient _containerServiceClient; - private NetmapService.NetmapServiceClient _netmapServiceClient; - private ObjectService.ObjectServiceClient _objectServiceClient; - private SessionService.SessionServiceClient _sessionServiceClient; + private ContainerService.ContainerServiceClient? _containerServiceClient; + private NetmapService.NetmapServiceClient? _netmapServiceClient; + private ObjectService.ObjectServiceClient? _objectServiceClient; + private SessionService.SessionServiceClient? _sessionServiceClient; public Client(string key, string host) { @@ -47,7 +48,7 @@ public partial class Client: IFrostFSClient throw new ApplicationException(msg); } } - + private void InitGrpcChannel(string host) { Uri uri; @@ -89,7 +90,7 @@ public partial class Client: IFrostFSClient { _netmapServiceClient = new NetmapService.NetmapServiceClient(_channel); } - + private void InitObjectClient() { _objectServiceClient = new ObjectService.ObjectServiceClient(_channel); diff --git a/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj b/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj index ec50a7a..0208178 100644 --- a/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj +++ b/src/FrostFS.SDK.ClientV2/FrostFS.SDK.ClientV2.csproj @@ -1,15 +1,19 @@ - + - - net6.0 - enable - enable - - - - - - - + + netstandard2.0 + 12.0 + enable + + + + + + + + + + + diff --git a/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs b/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs index 395d40a..8412c6c 100644 --- a/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs +++ b/src/FrostFS.SDK.ClientV2/Interfaces/IFrostFSClient.cs @@ -1,3 +1,7 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + using FrostFS.SDK.ModelsV2; namespace FrostFS.SDK.ClientV2.Interfaces; diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Container.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Container.cs index b258662..93eac3f 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Container.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Container.cs @@ -1,7 +1,10 @@ +using System; + +using Google.Protobuf; + using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; using FrostFS.SDK.Cryptography; using FrostFS.SDK.ModelsV2.Enums; -using Google.Protobuf; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -26,7 +29,7 @@ public static class ContainerMapper } return new ModelsV2.Container( - Enum.Parse(basicAclName), + (BasicAcl)Enum.Parse(typeof(BasicAcl), basicAclName), container.PlacementPolicy.ToModel() ) { diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/NodeInfo.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/NodeInfo.cs index bbafaad..f8f2d56 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/NodeInfo.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/NodeInfo.cs @@ -1,3 +1,5 @@ +using System; + using FrostFS.Netmap; using FrostFS.SDK.ModelsV2.Enums; using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo; @@ -15,7 +17,7 @@ public static class NodeInfoMapper } return new NodeInfo { - State = Enum.Parse(nodeStateName), + State = (NodeState)Enum.Parse(typeof(NodeState), nodeStateName), Version = nodeInfo.Version.ToModel() }; } diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/PlacementPolicy.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/PlacementPolicy.cs index de8e188..a4cbb0d 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/PlacementPolicy.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Netmap/PlacementPolicy.cs @@ -1,3 +1,4 @@ +using System.Linq; using FrostFS.Netmap; namespace FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Object.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Object.cs index 54f6617..b6e68f6 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Object.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Object.cs @@ -1,3 +1,6 @@ +using System; +using System.Linq; + using FrostFS.Object; using FrostFS.SDK.ModelsV2; using MatchType = FrostFS.Object.MatchType; @@ -26,15 +29,11 @@ public static class ObjectFilterMapper { public static SearchRequest.Types.Body.Types.Filter ToGrpcMessage(this ObjectFilter filter) { - var objMatchTypeName = Enum.GetName(typeof(MatchType), filter.MatchType); - if (objMatchTypeName is null) - { - throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'."); - } - + var objMatchTypeName = Enum.GetName(typeof(MatchType), filter.MatchType) + ?? throw new ArgumentException($"Unknown MatchType. Value: '{filter.MatchType}'."); return new SearchRequest.Types.Body.Types.Filter { - MatchType = Enum.Parse(objMatchTypeName), + MatchType = (MatchType)Enum.Parse(typeof(MatchType), objMatchTypeName), Key = filter.Key, Value = filter.Value }; @@ -45,18 +44,15 @@ public static class ObjectHeaderMapper { public static Header ToGrpcMessage(this ObjectHeader header) { - var objTypeName = Enum.GetName(typeof(ObjectType), header.ObjectType); - if (objTypeName is null) - { - throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'."); - } - + var objTypeName = Enum.GetName(typeof(ObjectType), header.ObjectType) + ?? throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'."); var head = new Header { Attributes = { }, ContainerId = header.ContainerId.ToGrpcMessage(), - ObjectType = Enum.Parse(objTypeName) + ObjectType = (ObjectType)Enum.Parse(typeof(ObjectType), objTypeName) }; + foreach (var attribute in header.Attributes) { head.Attributes.Add(attribute.ToGrpcMessage()); @@ -67,15 +63,11 @@ public static class ObjectHeaderMapper public static ObjectHeader ToModel(this Header header) { - var objTypeName = Enum.GetName(typeof(ModelsV2.Enums.ObjectType), header.ObjectType); - if (objTypeName is null) - { - throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'."); - } - + var objTypeName = Enum.GetName(typeof(ModelsV2.Enums.ObjectType), header.ObjectType) + ?? throw new ArgumentException($"Unknown ObjectType. Value: '{header.ObjectType}'."); return new ObjectHeader( ContainerId.FromHash(header.ContainerId.Value.ToByteArray()), - Enum.Parse(objTypeName), + (ModelsV2.Enums.ObjectType)Enum.Parse(typeof(ModelsV2.Enums.ObjectType), objTypeName), header.Attributes.Select(attribute => attribute.ToModel()).ToArray() ) { diff --git a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs index ec764f1..9e3d2eb 100644 --- a/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs +++ b/src/FrostFS.SDK.ClientV2/Mappers/GRPC/Status.cs @@ -1,3 +1,4 @@ +using System; using FrostFS.SDK.ModelsV2.Enums; namespace FrostFS.SDK.ClientV2.Mappers.GRPC; @@ -8,12 +9,9 @@ public static class StatusMapper { if (status is null) return new ModelsV2.Status(StatusCode.Success); var codeName = Enum.GetName(typeof(StatusCode), status.Code); - if (codeName is null) - { - throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'."); - } - - return new ModelsV2.Status(Enum.Parse(codeName), status.Message); - + + return codeName is null + ? throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.") + : new ModelsV2.Status((StatusCode)Enum.Parse(typeof(StatusCode), codeName), status.Message); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Range.cs b/src/FrostFS.SDK.ClientV2/Range.cs new file mode 100644 index 0000000..8158314 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Range.cs @@ -0,0 +1,271 @@ +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + { + return ~_value; + } + else + { + return _value; + } + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + var offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return "^" + ((uint)Value).ToString(); + + return ((uint)Value).ToString(); + } + } + + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + { + return Start.GetHashCode() * 31 + End.GetHashCode(); + } + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return Start + ".." + End; + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + var startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + var endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } + } +} + +namespace System.Runtime.CompilerServices +{ + internal static class RuntimeHelpers + { + /// + /// Slices the specified array using the specified range. + /// + public static T[] GetSubArray(T[] array, Range range) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + (int offset, int length) = range.GetOffsetAndLength(array.Length); + + if (default(T) != null || typeof(T[]) == array.GetType()) + { + // We know the type of the array to be exactly T[]. + + if (length == 0) + { + return Array.Empty(); + } + + var dest = new T[length]; + Array.Copy(array, offset, dest, 0, length); + return dest; + } + else + { + // The array is actually a U[] where U:T. + var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length); + Array.Copy(array, offset, dest, 0, length); + return dest; + } + } + } +} diff --git a/src/FrostFS.SDK.ClientV2/RequestSigner.cs b/src/FrostFS.SDK.ClientV2/RequestSigner.cs index 52fae36..3747c92 100644 --- a/src/FrostFS.SDK.ClientV2/RequestSigner.cs +++ b/src/FrostFS.SDK.ClientV2/RequestSigner.cs @@ -1,97 +1,106 @@ +using System; using System.Security.Cryptography; -using FrostFS.Refs; -using FrostFS.SDK.Cryptography; -using FrostFS.Session; + using Google.Protobuf; + using Org.BouncyCastle.Asn1.Sec; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; -namespace FrostFS.SDK.ClientV2 +using FrostFS.Refs; +using FrostFS.SDK.Cryptography; +using FrostFS.Session; + +namespace FrostFS.SDK.ClientV2; + +public static class RequestSigner { - public static class RequestSigner + public const int RFC6979SignatureSize = 64; + + public static byte[] SignRFC6979(this ECDsa key, byte[] data) { - public const int RFC6979SignatureSize = 64; + var digest = new Sha256Digest(); + var secp256R1 = SecNamedCurves.GetByName("secp256r1"); + var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N); + var privateKey = new ECPrivateKeyParameters(new BigInteger(1, key.PrivateKey()), ecParameters); + var signer = new ECDsaSigner(new HMacDsaKCalculator(digest)); + var hash = new byte[digest.GetDigestSize()]; + + digest.BlockUpdate(data, 0, data.Length); + digest.DoFinal(hash, 0); + signer.Init(true, privateKey); + + var rs = signer.GenerateSignature(hash); + var signature = new byte[RFC6979SignatureSize]; + var rbytes = rs[0].ToByteArrayUnsigned(); + var sbytes = rs[1].ToByteArrayUnsigned(); + var index = RFC6979SignatureSize / 2 - rbytes.Length; + + rbytes.CopyTo(signature, index); + index = RFC6979SignatureSize - sbytes.Length; + sbytes.CopyTo(signature, index); + + return signature; + } - public static byte[] SignRFC6979(this ECDsa key, byte[] data) + public static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message) + { + return new SignatureRFC6979 { - var digest = new Sha256Digest(); - var secp256R1 = SecNamedCurves.GetByName("secp256r1"); - var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N); - var privateKey = new ECPrivateKeyParameters(new BigInteger(1, key.PrivateKey()), ecParameters); - var signer = new ECDsaSigner(new HMacDsaKCalculator(digest)); - var hash = new byte[digest.GetDigestSize()]; - digest.BlockUpdate(data, 0, data.Length); - digest.DoFinal(hash, 0); - signer.Init(true, privateKey); - var rs = signer.GenerateSignature(hash); - var signature = new byte[RFC6979SignatureSize]; - var rbytes = rs[0].ToByteArrayUnsigned(); - var sbytes = rs[1].ToByteArrayUnsigned(); - var index = RFC6979SignatureSize / 2 - rbytes.Length; - rbytes.CopyTo(signature, index); - index = RFC6979SignatureSize - sbytes.Length; - sbytes.CopyTo(signature, index); - return signature; - } + Key = ByteString.CopyFrom(key.PublicKey()), + Sign = ByteString.CopyFrom(key.SignRFC6979(message.ToByteArray())), + }; + } + + public static SignatureRFC6979 SignRFC6979(this ECDsa key, ByteString data) + { + return new SignatureRFC6979 + { + Key = ByteString.CopyFrom(key.PublicKey()), + Sign = ByteString.CopyFrom(key.SignRFC6979(data.ToByteArray())), + }; + } - public static SignatureRFC6979 SignRFC6979(this ECDsa key, IMessage message) - { - return new SignatureRFC6979 - { - Key = ByteString.CopyFrom(key.PublicKey()), - Sign = ByteString.CopyFrom(key.SignRFC6979(message.ToByteArray())), - }; - } - - public static SignatureRFC6979 SignRFC6979(this ECDsa key, ByteString data) - { - return new SignatureRFC6979 - { - Key = ByteString.CopyFrom(key.PublicKey()), - Sign = ByteString.CopyFrom(key.SignRFC6979(data.ToByteArray())), - }; - } + public static byte[] SignData(this ECDsa key, byte[] data) + { + var hash = new byte[65]; + hash[0] = 0x04; + key + .SignHash(SHA512.Create().ComputeHash(data)) + .CopyTo(hash, 1); + return hash; + } - public static byte[] SignData(this ECDsa key, byte[] data) + public static Signature SignMessagePart(this ECDsa key, IMessage? data) + { + var data2Sign = data is null ? Array.Empty() : data.ToByteArray(); + var sig = new Signature { - var hash = new byte[65]; - hash[0] = 0x04; - key - .SignHash(SHA512.Create().ComputeHash(data)) - .CopyTo(hash, 1); - return hash; - } + Key = ByteString.CopyFrom(key.PublicKey()), + Sign = ByteString.CopyFrom(key.SignData(data2Sign)), + }; + return sig; + } - public static Signature SignMessagePart(this ECDsa key, IMessage? data) + public static void Sign(this IVerificableMessage message, ECDsa key) + { + var meta = message.GetMetaHeader(); + IVerificationHeader verify = message switch { - var data2Sign = data is null ? Array.Empty() : data.ToByteArray(); - var sig = new Signature - { - Key = ByteString.CopyFrom(key.PublicKey()), - Sign = ByteString.CopyFrom(key.SignData(data2Sign)), - }; - return sig; - } + IRequest => new RequestVerificationHeader(), + IResponse => new ResponseVerificationHeader(), + _ => throw new InvalidOperationException("Unsopported message type") + }; + + var verifyOrigin = message.GetVerificationHeader(); + if (verifyOrigin is null) + verify.BodySignature = key.SignMessagePart(message.GetBody()); - public static void Sign(this IVerificableMessage message, ECDsa key) - { - var meta = message.GetMetaHeader(); - IVerificationHeader verify = message switch - { - IRequest => new RequestVerificationHeader(), - IResponse => new ResponseVerificationHeader(), - _ => throw new InvalidOperationException("Unsopported message type") - }; - var verifyOrigin = message.GetVerificationHeader(); - if (verifyOrigin is null) - verify.BodySignature = key.SignMessagePart(message.GetBody()); - verify.MetaSignature = key.SignMessagePart(meta); - verify.OriginSignature = key.SignMessagePart(verifyOrigin); - verify.SetOrigin(verifyOrigin); - message.SetVerificationHeader(verify); - } + verify.MetaSignature = key.SignMessagePart(meta); + verify.OriginSignature = key.SignMessagePart(verifyOrigin); + verify.SetOrigin(verifyOrigin); + message.SetVerificationHeader(verify); } } diff --git a/src/FrostFS.SDK.ClientV2/Services/Container.cs b/src/FrostFS.SDK.ClientV2/Services/Container.cs index d0b54d9..886768c 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Container.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Container.cs @@ -1,6 +1,8 @@ using FrostFS.Container; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.ModelsV2; +using System.Collections.Generic; +using System.Threading.Tasks; namespace FrostFS.SDK.ClientV2; diff --git a/src/FrostFS.SDK.ClientV2/Services/Netmap.cs b/src/FrostFS.SDK.ClientV2/Services/Netmap.cs index c4f0386..ce439cc 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Netmap.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Netmap.cs @@ -1,5 +1,8 @@ -using FrostFS.Netmap; +using System.Threading.Tasks; + +using FrostFS.Netmap; using FrostFS.SDK.ClientV2.Mappers.GRPC.Netmap; + using NodeInfo = FrostFS.SDK.ModelsV2.Netmap.NodeInfo; namespace FrostFS.SDK.ClientV2; @@ -10,11 +13,13 @@ public partial class Client { var request = new LocalNodeInfoRequest { - Body = new LocalNodeInfoRequest.Types.Body { }, + Body = new LocalNodeInfoRequest.Types.Body { } }; + request.AddMetaHeader(); request.Sign(_key); var response = await _netmapServiceClient.LocalNodeInfoAsync(request); + return response.Body.ToModel(); } @@ -22,10 +27,12 @@ public partial class Client { var request = new NetworkInfoRequest { - Body = new NetworkInfoRequest.Types.Body { }, + Body = new NetworkInfoRequest.Types.Body { } }; + request.AddMetaHeader(); request.Sign(_key); + return await _netmapServiceClient.NetworkInfoAsync(request); } } diff --git a/src/FrostFS.SDK.ClientV2/Services/Object.cs b/src/FrostFS.SDK.ClientV2/Services/Object.cs index 62e2ba7..180e351 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Object.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Object.cs @@ -1,11 +1,16 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +using Google.Protobuf; + using FrostFS.Object; using FrostFS.Refs; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; using FrostFS.SDK.ModelsV2; using FrostFS.Session; -using Google.Protobuf; -using Grpc.Core; namespace FrostFS.SDK.ClientV2; @@ -15,19 +20,21 @@ public partial class Client { var request = new HeadRequest { - Body = new HeadRequest.Types.Body + Body = new HeadRequest.Types.Body { Address = new Address { ContainerId = cid.ToGrpcMessage(), ObjectId = oid.ToGrpcMessage() } - }, + } }; + request.AddMetaHeader(); request.Sign(_key); var response = await _objectServiceClient.HeadAsync(request); Verifier.CheckResponse(response); + return response.Body.Header.Header.ToModel(); } @@ -43,9 +50,10 @@ public partial class Client { ContainerId = cid.ToGrpcMessage(), ObjectId = oid.ToGrpcMessage() - }, + } } }; + request.AddMetaHeader(); request.AddObjectSessionToken( sessionToken, @@ -54,43 +62,13 @@ public partial class Client ObjectSessionContext.Types.Verb.Get, _key ); + request.Sign(_key); - var obj = await GetObject(request); + return obj.ToModel(); } - private async Task GetObject(GetRequest request) - { - using var stream = GetObjectInit(request); - var obj = await stream.ReadHeader(); - var payload = new byte[obj.Header.PayloadLength]; - var offset = 0; - var chunk = await stream.ReadChunk(); - while (chunk is not null) - { - chunk.CopyTo(payload, offset); - offset += chunk.Length; - chunk = await stream.ReadChunk(); - } - - obj.Payload = ByteString.CopyFrom(payload); - return obj; - } - - private ObjectReader GetObjectInit(GetRequest initRequest) - { - if (initRequest is null) - { - throw new ArgumentNullException(nameof(initRequest)); - } - - return new ObjectReader - { - Call = _objectServiceClient.Get(initRequest) - }; - } - public async Task PutObjectAsync(ObjectHeader header, Stream payload) { return await PutObject(header, payload); @@ -100,74 +78,12 @@ public partial class Client { return await PutObject(header, new MemoryStream(payload)); } - - private async Task PutObject(ObjectHeader header, Stream payload) - { - var sessionToken = await CreateSessionAsync(uint.MaxValue); - var hdr = header.ToGrpcMessage(); - hdr.OwnerId = OwnerId.ToGrpcMessage(); - hdr.Version = Version.ToGrpcMessage(); - var oid = new ObjectID - { - Value = hdr.Sha256() - }; - var request = new PutRequest - { - Body = new PutRequest.Types.Body - { - Init = new PutRequest.Types.Body.Types.Init - { - Header = hdr - }, - } - }; - request.AddMetaHeader(); - request.AddObjectSessionToken( - sessionToken, - hdr.ContainerId, - oid, - ObjectSessionContext.Types.Verb.Put, - _key - ); - request.Sign(_key); - - using var stream = await PutObjectInit(request); - var buffer = new byte[Constants.ObjectChunkSize]; - var bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize)); - while (bufferLength > 0) - { - request.Body = new PutRequest.Types.Body - { - Chunk = ByteString.CopyFrom(buffer[..bufferLength]), - }; - request.VerifyHeader = null; - request.Sign(_key); - await stream.Write(request); - bufferLength = await payload.ReadAsync(buffer.AsMemory(0, Constants.ObjectChunkSize)); - } - - var response = await stream.Close(); - Verifier.CheckResponse(response); - return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()); - } - - private async Task PutObjectInit(PutRequest initRequest) - { - if (initRequest is null) - { - throw new ArgumentNullException(nameof(initRequest)); - } - - var call = _objectServiceClient.Put(); - await call.RequestStream.WriteAsync(initRequest); - return new ObjectStreamer { Call = call }; - } public async Task DeleteObjectAsync(ContainerId cid, ObjectId oid) { var request = new DeleteRequest { - Body = new DeleteRequest.Types.Body + Body = new DeleteRequest.Types.Body { Address = new Address { @@ -176,6 +92,7 @@ public partial class Client } } }; + request.AddMetaHeader(); request.Sign(_key); var response = await _objectServiceClient.DeleteAsync(request); @@ -193,24 +110,125 @@ public partial class Client Version = 1 } }; + foreach (var filter in filters) { request.Body.Filters.Add(filter.ToGrpcMessage()); } - - ; + request.AddMetaHeader(); request.Sign(_key); var objectsIds = SearchObjects(request); + await foreach (var oid in objectsIds) { yield return ObjectId.FromHash(oid.Value.ToByteArray()); } } + private async Task GetObject(GetRequest request) + { + using var stream = GetObjectInit(request); + var obj = await stream.ReadHeader(); + var payload = new byte[obj.Header.PayloadLength]; + var offset = 0; + var chunk = await stream.ReadChunk(); + + while (chunk is not null) + { + chunk.CopyTo(payload, offset); + offset += chunk.Length; + chunk = await stream.ReadChunk(); + } + + obj.Payload = ByteString.CopyFrom(payload); + + return obj; + } + + private ObjectReader GetObjectInit(GetRequest initRequest) + { + if (initRequest is null) + throw new ArgumentNullException(nameof(initRequest)); + + return new ObjectReader + { + Call = _objectServiceClient.Get(initRequest) + }; + } + + private async Task PutObject(ObjectHeader header, Stream payload) + { + var sessionToken = await CreateSessionAsync(uint.MaxValue); + var hdr = header.ToGrpcMessage(); + hdr.OwnerId = OwnerId.ToGrpcMessage(); + hdr.Version = Version.ToGrpcMessage(); + + var oid = new ObjectID + { + Value = hdr.Sha256() + }; + + var request = new PutRequest + { + Body = new PutRequest.Types.Body + { + Init = new PutRequest.Types.Body.Types.Init + { + Header = hdr + }, + } + }; + + request.AddMetaHeader(); + request.AddObjectSessionToken( + sessionToken, + hdr.ContainerId, + oid, + ObjectSessionContext.Types.Verb.Put, + _key + ); + + request.Sign(_key); + + using var stream = await PutObjectInit(request); + var buffer = new byte[Constants.ObjectChunkSize]; + var bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize); + + while (bufferLength > 0) + { + request.Body = new PutRequest.Types.Body + { + Chunk = ByteString.CopyFrom(buffer[..bufferLength]), + }; + request.VerifyHeader = null; + request.Sign(_key); + await stream.Write(request); + bufferLength = await payload.ReadAsync(buffer, 0, Constants.ObjectChunkSize); + } + + var response = await stream.Close(); + Verifier.CheckResponse(response); + + return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray()); + } + + private async Task PutObjectInit(PutRequest initRequest) + { + if (initRequest is null) + { + throw new ArgumentNullException(nameof(initRequest)); + } + + var call = _objectServiceClient.Put(); + await call.RequestStream.WriteAsync(initRequest); + + return new ObjectStreamer(call); + } + private async IAsyncEnumerable SearchObjects(SearchRequest request) { - using var stream = SearchObjectsInit(request); + using var stream = GetSearchReader(request); var ids = await stream.Read(); while (ids is not null) { @@ -218,110 +236,18 @@ public partial class Client { yield return oid; } + ids = await stream.Read(); } } - private SearchReader SearchObjectsInit(SearchRequest initRequest) + private SearchReader GetSearchReader(SearchRequest initRequest) { if (initRequest is null) { throw new ArgumentNullException(nameof(initRequest)); } - return new SearchReader - { - Call = _objectServiceClient.Search(initRequest) - }; + return new SearchReader(_objectServiceClient.Search(initRequest)); } } - -internal class ObjectReader : IDisposable -{ - public AsyncServerStreamingCall Call { get; init; } - - public async Task ReadHeader() - { - if (!await Call.ResponseStream.MoveNext()) - { - throw new InvalidOperationException("unexpect end of stream"); - } - - var response = Call.ResponseStream.Current; - Verifier.CheckResponse(response); - if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init) - throw new InvalidOperationException("unexpect message type"); - return new Object.Object - { - ObjectId = response.Body.Init.ObjectId, - Header = response.Body.Init.Header, - }; - } - - public async Task ReadChunk() - { - if (!await Call.ResponseStream.MoveNext()) - { - return null; - } - - var response = Call.ResponseStream.Current; - Verifier.CheckResponse(response); - if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk) - throw new InvalidOperationException("unexpect message type"); - return response.Body.Chunk.ToByteArray(); - } - - public void Dispose() - { - Call.Dispose(); - } -} - -internal class ObjectStreamer : IDisposable -{ - public AsyncClientStreamingCall Call { get; init; } - - public async Task Write(PutRequest request) - { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - - await Call.RequestStream.WriteAsync(request); - } - - public async Task Close() - { - await Call.RequestStream.CompleteAsync(); - return await Call.ResponseAsync; - } - - public void Dispose() - { - Call.Dispose(); - } -} - -internal class SearchReader : IDisposable -{ - public AsyncServerStreamingCall Call { get; init; } - - public async Task?> Read() - { - if (!await Call.ResponseStream.MoveNext()) - { - return null; - } - - var response = Call.ResponseStream.Current; - Verifier.CheckResponse(response); - return response.Body?.IdList.ToList(); - } - - public void Dispose() - { - Call.Dispose(); - } -} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Services/ObjectReader.cs b/src/FrostFS.SDK.ClientV2/Services/ObjectReader.cs new file mode 100644 index 0000000..415c001 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Services/ObjectReader.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; + +using Grpc.Core; + +using FrostFS.Object; + +namespace FrostFS.SDK.ClientV2; + +internal class ObjectReader : IDisposable +{ + public AsyncServerStreamingCall Call { get; set; } + + public async Task ReadHeader() + { + if (!await Call.ResponseStream.MoveNext()) + throw new InvalidOperationException("unexpect end of stream"); + + var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); + + if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init) + throw new InvalidOperationException("unexpect message type"); + + return new Object.Object + { + ObjectId = response.Body.Init.ObjectId, + Header = response.Body.Init.Header, + }; + } + + public async Task ReadChunk() + { + if (!await Call.ResponseStream.MoveNext()) + return null; + + var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); + + if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk) + throw new InvalidOperationException("unexpect message type"); + + return response.Body.Chunk.ToByteArray(); + } + + public void Dispose() + { + Call.Dispose(); + } +} diff --git a/src/FrostFS.SDK.ClientV2/Services/ObjectStreamer.cs b/src/FrostFS.SDK.ClientV2/Services/ObjectStreamer.cs new file mode 100644 index 0000000..11858c3 --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Services/ObjectStreamer.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading.Tasks; + +using Grpc.Core; + +using FrostFS.Object; + +namespace FrostFS.SDK.ClientV2; + +internal class ObjectStreamer(AsyncClientStreamingCall call) : IDisposable +{ + public AsyncClientStreamingCall Call { get; private set; } = call; + + public async Task Write(PutRequest request) + { + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } + + await Call.RequestStream.WriteAsync(request); + } + + public async Task Close() + { + await Call.RequestStream.CompleteAsync(); + + return await Call.ResponseAsync; + } + + public void Dispose() + { + Call.Dispose(); + } +} diff --git a/src/FrostFS.SDK.ClientV2/Services/SearchReader.cs b/src/FrostFS.SDK.ClientV2/Services/SearchReader.cs new file mode 100644 index 0000000..c3d425a --- /dev/null +++ b/src/FrostFS.SDK.ClientV2/Services/SearchReader.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +using Grpc.Core; + +using FrostFS.Object; +using FrostFS.Refs; + +namespace FrostFS.SDK.ClientV2; + +internal class SearchReader(AsyncServerStreamingCall call) : IDisposable +{ + public AsyncServerStreamingCall Call { get; private set; } = call; + + public async Task?> Read() + { + if (!await Call.ResponseStream.MoveNext()) + { + return null; + } + + var response = Call.ResponseStream.Current; + Verifier.CheckResponse(response); + + return response.Body?.IdList.ToList(); + } + + public void Dispose() + { + Call.Dispose(); + } +} \ No newline at end of file diff --git a/src/FrostFS.SDK.ClientV2/Services/Session.cs b/src/FrostFS.SDK.ClientV2/Services/Session.cs index e1c2019..3dc52a1 100644 --- a/src/FrostFS.SDK.ClientV2/Services/Session.cs +++ b/src/FrostFS.SDK.ClientV2/Services/Session.cs @@ -1,3 +1,5 @@ +using System.Threading.Tasks; + using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.Session; @@ -15,14 +17,17 @@ public partial class Client Expiration = expiration, } }; + request.AddMetaHeader(); request.Sign(_key); + return await CreateSession(request); } private async Task CreateSession(CreateRequest request) { var resp = await _sessionServiceClient.CreateAsync(request); + return new SessionToken { Body = new SessionToken.Types.Body diff --git a/src/FrostFS.SDK.ClientV2/Verifier.cs b/src/FrostFS.SDK.ClientV2/Verifier.cs index f6bbe2a..ad6b3e6 100644 --- a/src/FrostFS.SDK.ClientV2/Verifier.cs +++ b/src/FrostFS.SDK.ClientV2/Verifier.cs @@ -1,89 +1,106 @@ +using System; using System.Security.Cryptography; -using FrostFS.Refs; -using FrostFS.SDK.ClientV2.Mappers.GRPC; -using FrostFS.SDK.Cryptography; -using FrostFS.Session; + using Google.Protobuf; + using Org.BouncyCastle.Asn1.Sec; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Math; -namespace FrostFS.SDK.ClientV2 +using FrostFS.Refs; +using FrostFS.SDK.ClientV2.Mappers.GRPC; +using FrostFS.SDK.Cryptography; +using FrostFS.Session; + +namespace FrostFS.SDK.ClientV2; + +public static class Verifier { - public static class Verifier + public const int RFC6979SignatureSize = 64; + + private static BigInteger[] DecodeSignature(byte[] sig) { - public const int RFC6979SignatureSize = 64; + if (sig.Length != RFC6979SignatureSize) + throw new FormatException($"Wrong signature size, expect={RFC6979SignatureSize}, actual={sig.Length}"); - private static BigInteger[] DecodeSignature(byte[] sig) - { - if (sig.Length != RFC6979SignatureSize) - throw new FormatException($"Wrong signature size, expect={RFC6979SignatureSize}, actual={sig.Length}"); - var rs = new BigInteger[2]; - rs[0] = new BigInteger(1, sig[..32]); - rs[1] = new BigInteger(1, sig[32..]); - return rs; - } + var rs = new BigInteger[2]; + rs[0] = new BigInteger(1, sig[..32]); + rs[1] = new BigInteger(1, sig[32..]); - public static bool VerifyRFC6979(this byte[] publicKey, byte[] data, byte[] sig) - { - if (publicKey is null || data is null || sig is null) return false; - var rs = DecodeSignature(sig); - var digest = new Sha256Digest(); - var signer = new ECDsaSigner(new HMacDsaKCalculator(digest)); - var secp256R1 = SecNamedCurves.GetByName("secp256r1"); - var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N); - var bcPublicKey = new ECPublicKeyParameters(secp256R1.Curve.DecodePoint(publicKey), ecParameters); - var hash = new byte[digest.GetDigestSize()]; - digest.BlockUpdate(data, 0, data.Length); - digest.DoFinal(hash, 0); - signer.Init(false, bcPublicKey); - return signer.VerifySignature(hash, rs[0], rs[1]); - } + return rs; + } - public static bool VerifyRFC6979(this SignatureRFC6979 signature, IMessage message) - { - return signature.Key.ToByteArray().VerifyRFC6979(message.ToByteArray(), signature.Sign.ToByteArray()); - } + public static bool VerifyRFC6979(this byte[] publicKey, byte[] data, byte[] sig) + { + if (publicKey is null || data is null || sig is null) + return false; - public static bool VerifyData(this ECDsa key, byte[] data, byte[] sig) - { - return key.VerifyHash(SHA512.Create().ComputeHash(data), sig[1..]); - } + var rs = DecodeSignature(sig); + var digest = new Sha256Digest(); + var signer = new ECDsaSigner(new HMacDsaKCalculator(digest)); + var secp256R1 = SecNamedCurves.GetByName("secp256r1"); + var ecParameters = new ECDomainParameters(secp256R1.Curve, secp256R1.G, secp256R1.N); + var bcPublicKey = new ECPublicKeyParameters(secp256R1.Curve.DecodePoint(publicKey), ecParameters); + var hash = new byte[digest.GetDigestSize()]; + + digest.BlockUpdate(data, 0, data.Length); + digest.DoFinal(hash, 0); + signer.Init(false, bcPublicKey); - public static bool VerifyMessagePart(this Signature sig, IMessage data) - { - if (sig is null || sig.Key is null || sig.Sign is null) return false; - using var key = sig.Key.ToByteArray().LoadPublicKey(); - var data2Verify = data is null ? Array.Empty() : data.ToByteArray(); - return key.VerifyData(data2Verify, sig.Sign.ToByteArray()); - } + return signer.VerifySignature(hash, rs[0], rs[1]); + } - public static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification) - { - if (!verification.MetaSignature.VerifyMessagePart(meta)) return false; - var origin = verification.GetOrigin(); - if (!verification.OriginSignature.VerifyMessagePart(origin)) return false; - if (origin is null) - return verification.BodySignature.VerifyMessagePart(body); - return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin); - } + public static bool VerifyRFC6979(this SignatureRFC6979 signature, IMessage message) + { + return signature.Key.ToByteArray().VerifyRFC6979(message.ToByteArray(), signature.Sign.ToByteArray()); + } - public static bool Verify(this IVerificableMessage message) - { - return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader()); - } + public static bool VerifyData(this ECDsa key, byte[] data, byte[] sig) + { + return key.VerifyHash(SHA512.Create().ComputeHash(data), sig[1..]); + } - public static void CheckResponse(IResponse resp) - { - if (!resp.Verify()) - throw new FormatException($"invalid response, type={resp.GetType()}"); - var status = resp.MetaHeader.Status.ToModel(); - if (!status.IsSuccess()) - { - throw new ApplicationException(status.ToString()); - } - } + public static bool VerifyMessagePart(this Signature sig, IMessage data) + { + if (sig is null || sig.Key is null || sig.Sign is null) + return false; + + using var key = sig.Key.ToByteArray().LoadPublicKey(); + var data2Verify = data is null ? Array.Empty() : data.ToByteArray(); + + return key.VerifyData(data2Verify, sig.Sign.ToByteArray()); + } + + public static bool VerifyMatryoskaLevel(IMessage body, IMetaHeader meta, IVerificationHeader verification) + { + if (!verification.MetaSignature.VerifyMessagePart(meta)) + return false; + + var origin = verification.GetOrigin(); + + if (!verification.OriginSignature.VerifyMessagePart(origin)) + return false; + + if (origin is null) + return verification.BodySignature.VerifyMessagePart(body); + + return verification.BodySignature is null && VerifyMatryoskaLevel(body, meta.GetOrigin(), origin); + } + + public static bool Verify(this IVerificableMessage message) + { + return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader()); + } + + public static void CheckResponse(IResponse resp) + { + if (!resp.Verify()) + throw new FormatException($"invalid response, type={resp.GetType()}"); + + var status = resp.MetaHeader.Status.ToModel(); + if (!status.IsSuccess()) + throw new ApplicationException(status.ToString()); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.Cryptography/ArrayHelper.cs b/src/FrostFS.SDK.Cryptography/ArrayHelper.cs index 1cb43fe..00c356d 100644 --- a/src/FrostFS.SDK.Cryptography/ArrayHelper.cs +++ b/src/FrostFS.SDK.Cryptography/ArrayHelper.cs @@ -1,23 +1,24 @@ +using System; +using System.Linq; using System.Runtime.CompilerServices; -namespace FrostFS.SDK.Cryptography +namespace FrostFS.SDK.Cryptography; + +internal static class ArrayHelper { - internal static class ArrayHelper + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] Concat(params byte[][] buffers) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static byte[] Concat(params byte[][] buffers) + var length = buffers.Sum(buffer => buffer.Length); + + var dst = new byte[length]; + var p = 0; + foreach (var src in buffers) { - var length = buffers.Sum(buffer => buffer.Length); - - var dst = new byte[length]; - var p = 0; - foreach (var src in buffers) - { - Buffer.BlockCopy(src, 0, dst, p, src.Length); - p += src.Length; - } - - return dst; + Buffer.BlockCopy(src, 0, dst, p, src.Length); + p += src.Length; } + + return dst; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs b/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs new file mode 100644 index 0000000..a593c3a --- /dev/null +++ b/src/FrostFS.SDK.Cryptography/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// In SDK-style projects such as this one, several assembly attributes that were historically +// defined in this file are now automatically added during build and populated with +// values defined in project properties. For details of which attributes are included +// and how to customise this process see: https://aka.ms/assembly-info-properties + + +// Setting ComVisible to false makes the types in this assembly not visible to COM +// components. If you need to access a type in this assembly from COM, set the ComVisible +// attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM. + +[assembly: Guid("08a8487e-39ce-41fb-9c24-13f73ff2bde0")] + +[assembly: InternalsVisibleToAttribute("FrostFS.SDK.Cryptography.Test")] \ No newline at end of file diff --git a/src/FrostFS.SDK.Cryptography/Base58.cs b/src/FrostFS.SDK.Cryptography/Base58.cs index 50670f5..36711c0 100644 --- a/src/FrostFS.SDK.Cryptography/Base58.cs +++ b/src/FrostFS.SDK.Cryptography/Base58.cs @@ -1,77 +1,97 @@ +using System; +using System.Linq; using System.Numerics; using System.Text; -namespace FrostFS.SDK.Cryptography +using Org.BouncyCastle.Security.Certificates; + +namespace FrostFS.SDK.Cryptography; + +public static class Base58 { - public static class Base58 + public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + + public static byte[] Base58CheckDecode(this string input) { - public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + if (input is null) + throw new ArgumentNullException(nameof(input)); + + byte[] buffer = Decode(input); - public static byte[] Base58CheckDecode(this string input) + if (buffer.Length < 4) + throw new FormatException(); + + byte[] checksum = buffer[0..(buffer.Length - 4)].Sha256().Sha256(); + + if (!buffer.AsSpan(buffer.Length - 4).SequenceEqual(checksum[..4].AsSpan())) + throw new FormatException(); + + var ret = buffer[..^4]; + Array.Clear(buffer, 0, buffer.Length); + return ret; + } + + public static string Base58CheckEncode(this ReadOnlySpan data) + { + byte[] checksum = data.ToArray().Sha256().Sha256(); + Span buffer = stackalloc byte[data.Length + 4]; + data.CopyTo(buffer); + checksum[..4].AsSpan().CopyTo(buffer[data.Length..]); + var ret = Encode(buffer); + buffer.Clear(); + return ret; + } + + public static byte[] Decode(string input) + { + // Decode Base58 string to BigInteger + var bi = BigInteger.Zero; + for (int i = 0; i < input.Length; i++) { - if (input is null) throw new ArgumentNullException(nameof(input)); - byte[] buffer = Decode(input); - if (buffer.Length < 4) throw new FormatException(); - byte[] checksum = buffer[0..(buffer.Length - 4)].Sha256().Sha256(); - if (!buffer.AsSpan(^4).SequenceEqual(checksum.AsSpan(..4))) - throw new FormatException(); - var ret = buffer[..^4]; - Array.Clear(buffer, 0, buffer.Length); - return ret; + int digit = Alphabet.IndexOf(input[i]); + if (digit < 0) + throw new FormatException($"Invalid Base58 character '{input[i]}' at position {i}"); + + bi = bi * Alphabet.Length + digit; } - public static string Base58CheckEncode(this ReadOnlySpan data) + int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count(); + var leadingZeros = new byte[leadingZeroCount]; + + if (bi.IsZero) + return leadingZeros; + + var bytesBigEndian = bi.ToByteArray().Reverse(); + + var firstNonZeroIndex = 0; + + while(bytesBigEndian.ElementAt(firstNonZeroIndex) == 0x0) + firstNonZeroIndex++; + + var bytesWithoutLeadingZeros = bytesBigEndian.Skip(firstNonZeroIndex).ToArray(); + + return ArrayHelper.Concat(leadingZeros, bytesWithoutLeadingZeros); + } + + public static string Encode(ReadOnlySpan input) + { + var data = input.ToArray().Reverse().Concat(new byte[] { 0 }).ToArray(); + BigInteger value = new(data); + + // Encode BigInteger to Base58 string + var sb = new StringBuilder(); + + while (value > 0) { - byte[] checksum = data.ToArray().Sha256().Sha256(); - Span buffer = stackalloc byte[data.Length + 4]; - data.CopyTo(buffer); - checksum.AsSpan(..4).CopyTo(buffer[data.Length..]); - var ret = Encode(buffer); - buffer.Clear(); - return ret; + value = BigInteger.DivRem(value, Alphabet.Length, out var remainder); + sb.Insert(0, Alphabet[(int)remainder]); } - public static byte[] Decode(string input) + // Append `1` for each leading 0 byte + for (int i = 0; i < input.Length && input[i] == 0; i++) { - // Decode Base58 string to BigInteger - var bi = BigInteger.Zero; - for (int i = 0; i < input.Length; i++) - { - int digit = Alphabet.IndexOf(input[i]); - if (digit < 0) - throw new FormatException($"Invalid Base58 character '{input[i]}' at position {i}"); - bi = bi * Alphabet.Length + digit; - } - - // Encode BigInteger to byte[] - // Leading zero bytes get encoded as leading `1` characters - int leadingZeroCount = input.TakeWhile(c => c == Alphabet[0]).Count(); - var leadingZeros = new byte[leadingZeroCount]; - if (bi.IsZero) return leadingZeros; - var bytesWithoutLeadingZeros = bi.ToByteArray(isUnsigned: true, isBigEndian: true); - return ArrayHelper.Concat(leadingZeros, bytesWithoutLeadingZeros); - } - - public static string Encode(ReadOnlySpan input) - { - // Decode byte[] to BigInteger - BigInteger value = new(input, isUnsigned: true, isBigEndian: true); - - // Encode BigInteger to Base58 string - var sb = new StringBuilder(); - - while (value > 0) - { - value = BigInteger.DivRem(value, Alphabet.Length, out var remainder); - sb.Insert(0, Alphabet[(int)remainder]); - } - - // Append `1` for each leading 0 byte - for (int i = 0; i < input.Length && input[i] == 0; i++) - { - sb.Insert(0, Alphabet[0]); - } - return sb.ToString(); + sb.Insert(0, Alphabet[0]); } + return sb.ToString(); } } diff --git a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj index a6cd5f3..0534720 100644 --- a/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj +++ b/src/FrostFS.SDK.Cryptography/FrostFS.SDK.Cryptography.csproj @@ -1,13 +1,15 @@ - + - - net6.0 - enable - enable - + + netstandard2.0 + 12.0 + enable + + + + + + + - - - - diff --git a/src/FrostFS.SDK.Cryptography/Helper.cs b/src/FrostFS.SDK.Cryptography/Helper.cs index 90f7150..93058d9 100644 --- a/src/FrostFS.SDK.Cryptography/Helper.cs +++ b/src/FrostFS.SDK.Cryptography/Helper.cs @@ -1,8 +1,8 @@ -using System.Buffers.Binary; -using System.Security.Cryptography; -using FrostFS.SDK.Cryptography.Tz; using Google.Protobuf; using Org.BouncyCastle.Crypto.Digests; +using System; +using System.Buffers.Binary; +using System.Security.Cryptography; namespace FrostFS.SDK.Cryptography; @@ -31,10 +31,8 @@ public static class Helper internal static byte[] Sha256(this ReadOnlySpan value) { - var buffer = new byte[32]; using var sha256 = SHA256.Create(); - sha256.TryComputeHash(value, buffer, out _); - return buffer; + return sha256.ComputeHash(value.ToArray()); } public static ByteString Sha256(this IMessage data) @@ -47,18 +45,7 @@ public static class Helper return ByteString.CopyFrom(data.ToByteArray().Sha256()); } - public static ByteString TzHash(this IMessage data) - { - return ByteString.CopyFrom(new TzHash().ComputeHash(data.ToByteArray())); - } - - public static ByteString TzHash(this ByteString data) - { - return ByteString.CopyFrom(new TzHash().ComputeHash(data.ToByteArray())); - } - - - + public static ulong Murmur64(this byte[] value, uint seed) { using var murmur = new Murmur3_128(seed); diff --git a/src/FrostFS.SDK.Cryptography/Key.cs b/src/FrostFS.SDK.Cryptography/Key.cs index 0c6e7ad..56f71cb 100644 --- a/src/FrostFS.SDK.Cryptography/Key.cs +++ b/src/FrostFS.SDK.Cryptography/Key.cs @@ -1,7 +1,10 @@ -using System.Buffers.Binary; +using System; +using System.Buffers.Binary; +using System.Linq; using System.Numerics; using System.Security.Cryptography; using System.Text; + using Org.BouncyCastle.Asn1.Sec; namespace FrostFS.SDK.Cryptography; @@ -22,8 +25,10 @@ public static class KeyExtension $"{nameof(Compress)} argument isn't uncompressed public key. " + $"expected length={UncompressedPublicKeyLength}, actual={publicKey.Length}" ); + var secp256R1 = SecNamedCurves.GetByName("secp256r1"); var point = secp256R1.Curve.DecodePoint(publicKey); + return point.GetEncoded(true); } @@ -34,8 +39,10 @@ public static class KeyExtension $"{nameof(Decompress)} argument isn't compressed public key. " + $"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}" ); + var secp256R1 = SecNamedCurves.GetByName("secp256r1"); var point = secp256R1.Curve.DecodePoint(publicKey); + return point.GetEncoded(false); } @@ -46,10 +53,12 @@ public static class KeyExtension $"{nameof(CreateSignatureRedeemScript)} argument isn't compressed public key. " + $"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}" ); + var script = new byte[] { 0x0c, CompressedPublicKeyLength }; //PUSHDATA1 33 script = ArrayHelper.Concat(script, publicKey); script = ArrayHelper.Concat(script, new byte[] { 0x41 }); //SYSCALL script = ArrayHelper.Concat(script, BitConverter.GetBytes(CheckSigDescriptor)); //Neo_Crypto_CheckSig + return script; } @@ -64,15 +73,20 @@ public static class KeyExtension Span data = stackalloc byte[21]; data[0] = version; scriptHash.CopyTo(data[1..]); + return Base58.Base58CheckEncode(data); } private static byte[] GetPrivateKeyFromWIF(string wif) { - if (wif == null) throw new ArgumentNullException(); + if (wif == null) + throw new ArgumentNullException(); + var data = wif.Base58CheckDecode(); + if (data.Length != 34 || data[0] != 0x80 || data[33] != 0x01) throw new FormatException(); + var privateKey = new byte[32]; Buffer.BlockCopy(data, 1, privateKey, 0, privateKey.Length); Array.Clear(data, 0, data.Length); @@ -92,6 +106,7 @@ public static class KeyExtension $" isn't encoded compressed public key. " + $"expected length={CompressedPublicKeyLength}, actual={publicKey.Length}" ); + return publicKey.GetScriptHash().ToAddress(NeoAddressVersion); } @@ -130,12 +145,14 @@ public static class KeyExtension Y = publicKey[32..] } }); + return key; } public static ECDsa LoadWif(this string wif) { var privateKey = GetPrivateKeyFromWIF(wif); + return LoadPrivateKey(privateKey); } @@ -151,6 +168,7 @@ public static class KeyExtension Y = publicKeyFull[32..] } }); + return key; } } \ No newline at end of file diff --git a/src/FrostFS.SDK.Cryptography/Murmur3_128.cs b/src/FrostFS.SDK.Cryptography/Murmur3_128.cs index 9975128..1a846ab 100644 --- a/src/FrostFS.SDK.Cryptography/Murmur3_128.cs +++ b/src/FrostFS.SDK.Cryptography/Murmur3_128.cs @@ -1,121 +1,125 @@ +using System; using System.Buffers.Binary; using System.Security.Cryptography; -namespace FrostFS.SDK.Cryptography +namespace FrostFS.SDK.Cryptography; + +internal class Murmur3_128 : HashAlgorithm { - internal class Murmur3_128 : HashAlgorithm + private const ulong c1 = 0x87c37b91114253d5; + private const ulong c2 = 0x4cf5ad432745937f; + private const uint m = 5; + private const uint n1 = 0x52dce729; + private const uint n2 = 0x38495ab5; + + private ulong h1; + private ulong h2; + private readonly uint seed; + private int length; + + public Murmur3_128(uint seed) { - private const ulong c1 = 0x87c37b91114253d5; - private const ulong c2 = 0x4cf5ad432745937f; - private const uint m = 5; - private const uint n1 = 0x52dce729; - private const uint n2 = 0x38495ab5; + this.seed = seed; + Initialize(); + } - private ulong h1; - private ulong h2; - private readonly uint seed; - private int length; - - public Murmur3_128(uint seed) + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + length += cbSize; + int remainder = cbSize & 15; + int alignedLength = ibStart + (cbSize - remainder); + + for (int i = ibStart; i < alignedLength; i += 16) { - this.seed = seed; - Initialize(); - } + ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i)); + ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8)); - protected override void HashCore(byte[] array, int ibStart, int cbSize) - { - length += cbSize; - int remainder = cbSize & 15; - int alignedLength = ibStart + (cbSize - remainder); - for (int i = ibStart; i < alignedLength; i += 16) - { - ulong k1 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i)); - ulong k2 = BinaryPrimitives.ReadUInt64LittleEndian(array.AsSpan(i + 8)); - - k1 *= c1; - k1 = (k1 << 31) | (k1 >> 33); - k1 *= c2; - h1 ^= k1; - h1 = (h1 << 27) | (h1 >> 37); - h1 += h2; - h1 = h1 * m + n1; - - k2 *= c2; - k2 = (k2 << 33) | (k2 >> 31); - k2 *= c1; - h2 ^= k2; - h2 = (h2 << 31) | (h2 >> 33); - h2 += h1; - h2 = h2 * m + n2; - } - if (remainder > 0) - { - ulong k1 = 0, k2 = 0; - switch (remainder) - { - case 15: k2 ^= (ulong)array[alignedLength + 14] << 48; goto case 14; - case 14: k2 ^= (ulong)array[alignedLength + 13] << 40; goto case 13; - case 13: k2 ^= (ulong)array[alignedLength + 12] << 32; goto case 12; - case 12: k2 ^= (ulong)array[alignedLength + 11] << 24; goto case 11; - case 11: k2 ^= (ulong)array[alignedLength + 10] << 16; goto case 10; - case 10: k2 ^= (ulong)array[alignedLength + 9] << 8; goto case 9; - case 9: - { - k2 ^= (ulong)array[alignedLength + 8]; - k2 *= c2; - k2 = (k2 << 33) | (k2 >> 31); - k2 *= c1; - h2 ^= k2; - goto case 8; - } - case 8: k1 ^= (ulong)array[alignedLength + 7] << 56; goto case 7; - case 7: k1 ^= (ulong)array[alignedLength + 6] << 48; goto case 6; - case 6: k1 ^= (ulong)array[alignedLength + 5] << 40; goto case 5; - case 5: k1 ^= (ulong)array[alignedLength + 4] << 32; goto case 4; - case 4: k1 ^= (ulong)array[alignedLength + 3] << 24; goto case 3; - case 3: k1 ^= (ulong)array[alignedLength + 2] << 16; goto case 2; - case 2: k1 ^= (ulong)array[alignedLength + 1] << 8; goto case 1; - case 1: - { - k1 ^= (ulong)array[alignedLength]; - k1 *= c1; - k1 = (k1 << 31) | (k1 >> 33); - k1 *= c2; - h1 ^= k1; - break; - } - } - } - } - - protected override byte[] HashFinal() - { - h1 ^= (ulong)length; - h2 ^= (ulong)length; + k1 *= c1; + k1 = (k1 << 31) | (k1 >> 33); + k1 *= c2; + h1 ^= k1; + h1 = (h1 << 27) | (h1 >> 37); h1 += h2; - h2 += h1; - h1 = Fimix64(h1); - h2 = Fimix64(h2); - h1 += h2; - h2 += h1; - return BitConverter.GetBytes(h1); - } + h1 = h1 * m + n1; - public override void Initialize() - { - length = 0; - h1 = seed; - h2 = seed; + k2 *= c2; + k2 = (k2 << 33) | (k2 >> 31); + k2 *= c1; + h2 ^= k2; + h2 = (h2 << 31) | (h2 >> 33); + h2 += h1; + h2 = h2 * m + n2; } - - private ulong Fimix64(ulong k) + + if (remainder > 0) { - k ^= k >> 33; - k *= 0xff51afd7ed558ccd; - k ^= k >> 33; - k *= 0xc4ceb9fe1a85ec53; - k ^= k >> 33; - return k; + ulong k1 = 0, k2 = 0; + switch (remainder) + { + case 15: k2 ^= (ulong)array[alignedLength + 14] << 48; goto case 14; + case 14: k2 ^= (ulong)array[alignedLength + 13] << 40; goto case 13; + case 13: k2 ^= (ulong)array[alignedLength + 12] << 32; goto case 12; + case 12: k2 ^= (ulong)array[alignedLength + 11] << 24; goto case 11; + case 11: k2 ^= (ulong)array[alignedLength + 10] << 16; goto case 10; + case 10: k2 ^= (ulong)array[alignedLength + 9] << 8; goto case 9; + case 9: + { + k2 ^= (ulong)array[alignedLength + 8]; + k2 *= c2; + k2 = (k2 << 33) | (k2 >> 31); + k2 *= c1; + h2 ^= k2; + goto case 8; + } + case 8: k1 ^= (ulong)array[alignedLength + 7] << 56; goto case 7; + case 7: k1 ^= (ulong)array[alignedLength + 6] << 48; goto case 6; + case 6: k1 ^= (ulong)array[alignedLength + 5] << 40; goto case 5; + case 5: k1 ^= (ulong)array[alignedLength + 4] << 32; goto case 4; + case 4: k1 ^= (ulong)array[alignedLength + 3] << 24; goto case 3; + case 3: k1 ^= (ulong)array[alignedLength + 2] << 16; goto case 2; + case 2: k1 ^= (ulong)array[alignedLength + 1] << 8; goto case 1; + case 1: + { + k1 ^= (ulong)array[alignedLength]; + k1 *= c1; + k1 = (k1 << 31) | (k1 >> 33); + k1 *= c2; + h1 ^= k1; + break; + } + } } } + + protected override byte[] HashFinal() + { + h1 ^= (ulong)length; + h2 ^= (ulong)length; + h1 += h2; + h2 += h1; + h1 = Fimix64(h1); + h2 = Fimix64(h2); + h1 += h2; + h2 += h1; + + return BitConverter.GetBytes(h1); + } + + public override void Initialize() + { + length = 0; + h1 = seed; + h2 = seed; + } + + private ulong Fimix64(ulong k) + { + k ^= k >> 33; + k *= 0xff51afd7ed558ccd; + k ^= k >> 33; + k *= 0xc4ceb9fe1a85ec53; + k ^= k >> 33; + + return k; + } } diff --git a/src/FrostFS.SDK.Cryptography/Range.cs b/src/FrostFS.SDK.Cryptography/Range.cs new file mode 100644 index 0000000..8158314 --- /dev/null +++ b/src/FrostFS.SDK.Cryptography/Range.cs @@ -0,0 +1,271 @@ +using System.Runtime.CompilerServices; + +namespace System +{ + /// Represent a type can be used to index a collection either from the start or the end. + /// + /// Index is used by the C# compiler to support the new index syntax + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ; + /// int lastElement = someArray[^1]; // lastElement = 5 + /// + /// + internal readonly struct Index : IEquatable + { + private readonly int _value; + + /// Construct an Index using a value and indicating if the index is from the start or from the end. + /// The index value. it has to be zero or positive number. + /// Indicating if the index is from the start or from the end. + /// + /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Index(int value, bool fromEnd = false) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + if (fromEnd) + _value = ~value; + else + _value = value; + } + + // The following private constructors mainly created for perf reason to avoid the checks + private Index(int value) + { + _value = value; + } + + /// Create an Index pointing at first element. + public static Index Start => new Index(0); + + /// Create an Index pointing at beyond last element. + public static Index End => new Index(~0); + + /// Create an Index from the start at the position indicated by the value. + /// The index value from the start. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromStart(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(value); + } + + /// Create an Index from the end at the position indicated by the value. + /// The index value from the end. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Index FromEnd(int value) + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(value), "value must be non-negative"); + } + + return new Index(~value); + } + + /// Returns the index value. + public int Value + { + get + { + if (_value < 0) + { + return ~_value; + } + else + { + return _value; + } + } + } + + /// Indicates whether the index is from the start or the end. + public bool IsFromEnd => _value < 0; + + /// Calculate the offset from the start using the giving collection length. + /// The length of the collection that the Index will be used with. length has to be a positive value + /// + /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values. + /// we don't validate either the returned offset is greater than the input length. + /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and + /// then used to index a collection will get out of range exception which will be same affect as the validation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int GetOffset(int length) + { + var offset = _value; + if (IsFromEnd) + { + // offset = length - (~value) + // offset = length + (~(~value) + 1) + // offset = length + value + 1 + + offset += length + 1; + } + return offset; + } + + /// Indicates whether the current Index object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => value is Index && _value == ((Index)value)._value; + + /// Indicates whether the current Index object is equal to another Index object. + /// An object to compare with this object + public bool Equals(Index other) => _value == other._value; + + /// Returns the hash code for this instance. + public override int GetHashCode() => _value; + + /// Converts integer number to an Index. + public static implicit operator Index(int value) => FromStart(value); + + /// Converts the value of the current Index object to its equivalent string representation. + public override string ToString() + { + if (IsFromEnd) + return "^" + ((uint)Value).ToString(); + + return ((uint)Value).ToString(); + } + } + + /// Represent a range has start and end indexes. + /// + /// Range is used by the C# compiler to support the range syntax. + /// + /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 }; + /// int[] subArray1 = someArray[0..2]; // { 1, 2 } + /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 } + /// + /// + internal readonly struct Range : IEquatable + { + /// Represent the inclusive start index of the Range. + public Index Start { get; } + + /// Represent the exclusive end index of the Range. + public Index End { get; } + + /// Construct a Range object using the start and end indexes. + /// Represent the inclusive start index of the range. + /// Represent the exclusive end index of the range. + public Range(Index start, Index end) + { + Start = start; + End = end; + } + + /// Indicates whether the current Range object is equal to another object of the same type. + /// An object to compare with this object + public override bool Equals(object? value) => + value is Range r && + r.Start.Equals(Start) && + r.End.Equals(End); + + /// Indicates whether the current Range object is equal to another Range object. + /// An object to compare with this object + public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End); + + /// Returns the hash code for this instance. + public override int GetHashCode() + { + return Start.GetHashCode() * 31 + End.GetHashCode(); + } + + /// Converts the value of the current Range object to its equivalent string representation. + public override string ToString() + { + return Start + ".." + End; + } + + /// Create a Range object starting from start index to the end of the collection. + public static Range StartAt(Index start) => new Range(start, Index.End); + + /// Create a Range object starting from first element in the collection to the end Index. + public static Range EndAt(Index end) => new Range(Index.Start, end); + + /// Create a Range object starting from first element to the end. + public static Range All => new Range(Index.Start, Index.End); + + /// Calculate the start offset and length of range object using a collection length. + /// The length of the collection that the range will be used with. length has to be a positive value. + /// + /// For performance reason, we don't validate the input length parameter against negative values. + /// It is expected Range will be used with collections which always have non negative length/count. + /// We validate the range is inside the length scope though. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (int Offset, int Length) GetOffsetAndLength(int length) + { + int start; + var startIndex = Start; + if (startIndex.IsFromEnd) + start = length - startIndex.Value; + else + start = startIndex.Value; + + int end; + var endIndex = End; + if (endIndex.IsFromEnd) + end = length - endIndex.Value; + else + end = endIndex.Value; + + if ((uint)end > (uint)length || (uint)start > (uint)end) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + + return (start, end - start); + } + } +} + +namespace System.Runtime.CompilerServices +{ + internal static class RuntimeHelpers + { + /// + /// Slices the specified array using the specified range. + /// + public static T[] GetSubArray(T[] array, Range range) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + (int offset, int length) = range.GetOffsetAndLength(array.Length); + + if (default(T) != null || typeof(T[]) == array.GetType()) + { + // We know the type of the array to be exactly T[]. + + if (length == 0) + { + return Array.Empty(); + } + + var dest = new T[length]; + Array.Copy(array, offset, dest, 0, length); + return dest; + } + else + { + // The array is actually a U[] where U:T. + var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length); + Array.Copy(array, offset, dest, 0, length); + return dest; + } + } + } +} diff --git a/src/FrostFS.SDK.Cryptography/Tz/GF127.cs b/src/FrostFS.SDK.Cryptography/Tz/GF127.cs index 260d627..d1abdcf 100644 --- a/src/FrostFS.SDK.Cryptography/Tz/GF127.cs +++ b/src/FrostFS.SDK.Cryptography/Tz/GF127.cs @@ -1,253 +1,253 @@ -using System.Security.Cryptography; +using System; +using System.Security.Cryptography; -namespace FrostFS.SDK.Cryptography.Tz +namespace FrostFS.SDK.Cryptography.Tz; + +// GF127 represents element of GF(2^127) +public class GF127 : IEquatable { - // GF127 represents element of GF(2^127) - public class GF127 : IEquatable + public const int ByteSize = 16; + 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] { - public const int ByteSize = 16; - 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 + get { return _data[index]; } + set { _data[index] = value; } + } - private readonly ulong[] _data; + public GF127(ulong[] value) + { + if (value is null || value.Length != 2) + throw new ArgumentException(nameof(value) + "is invalid"); + _data = value; + } - public ulong this[int index] - { - get { return _data[index]; } - set { _data[index] = 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(ulong[] value) - { - if (value is null || value.Length != 2) - throw new ArgumentException(nameof(value) + "is invalid"); - _data = value; - } + public GF127() : this(0, 0) + { + } - // 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); + 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() + 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) { - 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++) { - for (int i = 0; i < b[0].GetNonZeroLength(); i++) - { - if ((b[0] & ((ulong)1 << i)) != 0) - r += c; - c = Mul10(c); // c = c * 2 - } + if ((b[0] & ((ulong)1 << i)) != 0) + r += c; + c = Mul10(c); // c = c * 2 } - else + } + else + { + for (int i = 0; i < 64; i++) { - 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); - } + if ((b[0] & ((ulong)1 << i)) != 0) + r += c; + c = Mul10(c); // c = c * 2 } - return r; + for (int i = 0; i < b[1].GetNonZeroLength(); i++) + { + if ((b[1] & ((ulong)1 << i)) != 0) + r += c; + c = Mul10(c); + } } - // 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) + 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) { - 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) { - 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(); + (v, u) = (u, v); + (dv, du) = (du, dv); + (d, c) = (c, d); } - return c; + 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(); } - // 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 c; + } - return b; - } - - // Mul11 returns a*(x+1) - public static GF127 Mul11(GF127 a) + // 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) { - 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() + 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) { - using RandomNumberGenerator rng = RandomNumberGenerator.Create(); - return new GF127(rng.NextUlong(), rng.NextUlong() >> 1); + Array.Reverse(t0); + Array.Reverse(t1); } - // FromByteArray does the deserialization stuff - public GF127 FromByteArray(byte[] data) + _data[0] = BitConverter.ToUInt64(t0, 0); + _data[1] = BitConverter.ToUInt64(t1, 0); + 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) { - 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; + Array.Reverse(b0); + Array.Reverse(b1); } - // 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; + } - 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()); - } + // ToString() returns hex-encoded representation, starting with MSB. + public override string ToString() + { + return BitConverter.ToString(ToByteArray()).Replace("-", ""); } } \ No newline at end of file diff --git a/src/FrostFS.SDK.Cryptography/Tz/Helper.cs b/src/FrostFS.SDK.Cryptography/Tz/Helper.cs index 4aa11ce..807870e 100644 --- a/src/FrostFS.SDK.Cryptography/Tz/Helper.cs +++ b/src/FrostFS.SDK.Cryptography/Tz/Helper.cs @@ -1,30 +1,30 @@ -using System.Security.Cryptography; +using System; +using System.Security.Cryptography; -namespace FrostFS.SDK.Cryptography.Tz +namespace FrostFS.SDK.Cryptography.Tz; + +public static class Helper { - public static class Helper + public static ulong NextUlong(this RandomNumberGenerator rng) { - public static ulong NextUlong(this RandomNumberGenerator rng) - { - var buff = new byte[8]; - rng.GetBytes(buff); - return BitConverter.ToUInt64(buff, 0); - } + var buff = new byte[8]; + rng.GetBytes(buff); + return BitConverter.ToUInt64(buff, 0); + } - public static int GetLeadingZeros(ulong value) + public static int GetLeadingZeros(ulong value) + { + var i = 64; + while (value != 0) { - var i = 64; - while (value != 0) - { - value >>= 1; - i--; - } - return i; + value >>= 1; + i--; } + return i; + } - public static int GetNonZeroLength(this ulong value) - { - return 64 - GetLeadingZeros(value); - } + public static int GetNonZeroLength(this ulong value) + { + return 64 - GetLeadingZeros(value); } } diff --git a/src/FrostFS.SDK.Cryptography/Tz/SL2.cs b/src/FrostFS.SDK.Cryptography/Tz/SL2.cs index 9949681..6802501 100644 --- a/src/FrostFS.SDK.Cryptography/Tz/SL2.cs +++ b/src/FrostFS.SDK.Cryptography/Tz/SL2.cs @@ -1,177 +1,179 @@ -namespace FrostFS.SDK.Cryptography.Tz +using System; +using System.Linq; + +namespace FrostFS.SDK.Cryptography.Tz; + +public class SL2 : IEquatable { - public class SL2 : IEquatable + // 2x2 matrix + private readonly GF127[][] data; + + public static readonly SL2 ID = new( + new GF127(1, 0), new GF127(0, 0), new GF127(0, 0), new GF127(1, 0)); + + public static readonly SL2 A = new( + new GF127(2, 0), new GF127(1, 0), new GF127(1, 0), new GF127(0, 0)); + + public static readonly SL2 B = new( + new GF127(2, 0), new GF127(3, 0), new GF127(1, 0), new GF127(1, 0)); + + // Indexer + public GF127[] this[int i] { - // 2x2 matrix - private readonly GF127[][] data; + get { return data[i]; } + set { data[i] = value; } + } - public static readonly SL2 ID = new(new GF127(1, 0), new GF127(0, 0), - new GF127(0, 0), new GF127(1, 0)); - public static readonly SL2 A = new(new GF127(2, 0), new GF127(1, 0), - new GF127(1, 0), new GF127(0, 0)); - public static readonly SL2 B = new(new GF127(2, 0), new GF127(3, 0), - new GF127(1, 0), new GF127(1, 0)); + public SL2(GF127[][] value) + { + if (value is null || value.Length != 2 || !value.All(p => p.Length == 2)) + throw new ArgumentException(nameof(value) + $" invalid {nameof(GF127)} matrics"); + data = value; + } - // Indexer - public GF127[] this[int i] - { - get { return data[i]; } - set { data[i] = value; } - } + public SL2(GF127 g00, GF127 g01, GF127 g10, GF127 g11) + : this([[g00, g01], [g10, g11]]) + { + } - public SL2(GF127[][] value) - { - if (value is null || value.Length != 2 || !value.All(p => p.Length == 2)) - throw new ArgumentException(nameof(value) + $" invalid {nameof(GF127)} matrics"); - data = value; - } + public SL2() : this(GF127.One, GF127.Zero, GF127.Zero, GF127.One) + { + } - public SL2(GF127 g00, GF127 g01, GF127 g10, GF127 g11) - : this(new GF127[][] { new[] { g00, g01 }, new[] { g10, g11 } }) - { - } - - public SL2() : this(GF127.One, GF127.Zero, GF127.Zero, GF127.One) - { - } - - public override bool Equals(object obj) - { - if (obj is null) - return false; - if (ReferenceEquals(this, obj)) - return true; - if (obj is SL2 b) - return Equals(b); + public override bool Equals(object obj) + { + if (obj is null) return false; - } + if (ReferenceEquals(this, obj)) + return true; + if (obj is SL2 b) + return Equals(b); + return false; + } - public override int GetHashCode() - { - return this[0][0].GetHashCode() + - this[0][1].GetHashCode() + - this[1][0].GetHashCode() + - this[1][1].GetHashCode(); - } + public override int GetHashCode() + { + return this[0][0].GetHashCode() + + this[0][1].GetHashCode() + + this[1][0].GetHashCode() + + this[1][1].GetHashCode(); + } - public bool Equals(SL2 other) - { - if (other is null) - return false; - if (ReferenceEquals(this, other)) - return true; - return this[0][0].Equals(other[0][0]) && - this[0][1].Equals(other[0][1]) && - this[1][0].Equals(other[1][0]) && - this[1][1].Equals(other[1][1]); - } + public bool Equals(SL2 other) + { + if (other is null) + return false; + if (ReferenceEquals(this, other)) + return true; + return this[0][0].Equals(other[0][0]) && + this[0][1].Equals(other[0][1]) && + this[1][0].Equals(other[1][0]) && + this[1][1].Equals(other[1][1]); + } + // 2X2 matrix multiplication + public static SL2 operator *(SL2 a, SL2 b) + { + return new SL2( + a[0][0] * b[0][0] + a[0][1] * b[1][0], + a[0][0] * b[0][1] + a[0][1] * b[1][1], + a[1][0] * b[0][0] + a[1][1] * b[1][0], + a[1][0] * b[0][1] + a[1][1] * b[1][1]); + } - // 2X2 matrix multiplication - public static SL2 operator *(SL2 a, SL2 b) - { - return new SL2(a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1], - a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]); - } + // Multiplication using strassen algorithm + public static SL2 MulStrassen(SL2 a, SL2 b) + { + GF127[] t = + [ + (a[0][0] + a[1][1]) * (b[0][0] + b[1][1]), // t[0] == (a11 + a22) * (b11 + b22) + (a[1][0] + a[1][1]) * b[0][0], // t[1] == (a21 + a22) * b11 + (b[0][1] + b[1][1]) * a[0][0], // t[2] == (b12 + b22) * a11 + (b[1][0] + b[0][0]) * a[1][1], // t[3] == (b21 + b11) * a22 + (a[0][0] + a[0][1]) * b[1][1], // t[4] == (a11 + a12) * b22 + (a[1][0] + a[0][0]) * (b[0][0] + b[0][1]), // t[5] == (a21 + a11) * (b11 + b12) + (a[0][1] + a[1][1]) * (b[1][0] + b[1][1]), // t[6] == (a12 + a22) * (b21 + b22) + ]; - // Multiplication using strassen algorithm - public static SL2 MulStrassen(SL2 a, SL2 b) - { - GF127[] t = new GF127[7]; - t[0] = (a[0][0] + a[1][1]) * (b[0][0] + b[1][1]); // t[0] == (a11 + a22) * (b11 + b22) + SL2 r = new(); + r[0][1] = t[2] + t[4]; // r12 == a11*b12 + a11*b22 + a11*b22 + a12*b22 == a11*b12 + a12*b22 + r[1][0] = t[1] + t[3]; // r21 == a21*b11 + a22*b11 + a22*b21 + a22*b11 == a21*b11 + a22*b21 + // r11 == (a11*b11 + a22*b11` + a11*b22` + a22*b22`) + (a22*b21` + a22*b11`) + (a11*b22` + a12*b22`) + + // (a12*b21 + a22*b21` + a12*b22` + a22*b22`) == a11*b11 + a12*b21 + r[0][0] = t[0] + t[3] + t[4] + t[6]; + // r22 == (a11*b11` + a22*b11` + a11*b22` + a22*b22) + (a21*b11` + a22*b11`) + (a11*b12` + a11*b22`) + + // (a21*b11` + a11*b11` + a21*b12 + a11*b12`) == a21*b12 + a22*b22 + r[1][1] = t[0] + t[1] + t[2] + t[5]; - t[1] = (a[1][0] + a[1][1]) * b[0][0]; // t[1] == (a21 + a22) * b11 + return r; + } - t[2] = (b[0][1] + b[1][1]) * a[0][0]; // t[2] == (b12 + b22) * a11 + // Inv() returns inverse of a in SL2(GF(2^127)) + public static SL2 Inv(SL2 a) + { + GF127[] t = new GF127[2]; + t[0] = a[0][0] * a[1][1] + a[0][1] * a[1][0]; + t[1] = GF127.Inv(t[0]); - t[3] = (b[1][0] + b[0][0]) * a[1][1]; // t[3] == (b21 + b11) * a22 + SL2 r = new(); + r[1][1] = t[1] * a[0][0]; + r[0][1] = t[1] * a[0][1]; + r[1][0] = t[1] * a[1][0]; + r[0][0] = t[1] * a[1][1]; - t[4] = (a[0][0] + a[0][1]) * b[1][1]; // t[4] == (a11 + a12) * b22 + return r; + } - t[5] = (a[1][0] + a[0][0]) * (b[0][0] + b[0][1]); // t[5] == (a21 + a11) * (b11 + b12) + // MulA() returns this*A, A = {{x, 1}, {1, 0}} + public SL2 MulA() + { + var r = new SL2(); + r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12 + r[0][1] = this[0][0]; // r12 == t11 - t[6] = (a[0][1] + a[1][1]) * (b[1][0] + b[1][1]); // t[6] == (a12 + a22) * (b21 + b22) + r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22 + r[1][1] = this[1][0]; // r22 == t21 - SL2 r = new(); - r[0][1] = t[2] + t[4]; // r12 == a11*b12 + a11*b22 + a11*b22 + a12*b22 == a11*b12 + a12*b22 - r[1][0] = t[1] + t[3]; // r21 == a21*b11 + a22*b11 + a22*b21 + a22*b11 == a21*b11 + a22*b21 - // r11 == (a11*b11 + a22*b11` + a11*b22` + a22*b22`) + (a22*b21` + a22*b11`) + (a11*b22` + a12*b22`) + - // (a12*b21 + a22*b21` + a12*b22` + a22*b22`) == a11*b11 + a12*b21 - r[0][0] = t[0] + t[3] + t[4] + t[6]; - // r22 == (a11*b11` + a22*b11` + a11*b22` + a22*b22) + (a21*b11` + a22*b11`) + (a11*b12` + a11*b22`) + - // (a21*b11` + a11*b11` + a21*b12 + a11*b12`) == a21*b12 + a22*b22 - r[1][1] = t[0] + t[1] + t[2] + t[5]; + return r; + } - return r; - } + // MulB() returns this*B, B = {{x, x+1}, {1, 1}} + public SL2 MulB() + { + var r = new SL2(); + r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12 + r[0][1] = GF127.Mul10(this[0][0]) + this[0][0] + this[0][1]; // r12 == t11*x + t11 + t12 - // Inv() returns inverse of a in SL2(GF(2^127)) - public static SL2 Inv(SL2 a) - { - GF127[] t = new GF127[2]; - t[0] = a[0][0] * a[1][1] + a[0][1] * a[1][0]; // - t[1] = GF127.Inv(t[0]); + r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22 + r[1][1] = GF127.Mul10(this[1][0]) + this[1][0] + this[1][1]; // r22 == t21*x + t21 + t22 - SL2 r = new(); - r[1][1] = t[1] * a[0][0]; - r[0][1] = t[1] * a[0][1]; - r[1][0] = t[1] * a[1][0]; - r[0][0] = t[1] * a[1][1]; + return r; + } - return r; - } + public SL2 FromByteArray(byte[] data) + { + if (data.Length != 64) + throw new ArgumentException(nameof(SL2) + $" invalid data, exect={64}, ecatual={data.Length}"); + this[0][0] = new GF127().FromByteArray(data[0..16]); + this[0][1] = new GF127().FromByteArray(data[16..32]); + this[1][0] = new GF127().FromByteArray(data[32..48]); + this[1][1] = new GF127().FromByteArray(data[48..64]); + return this; + } - // MulA() returns this*A, A = {{x, 1}, {1, 0}} - public SL2 MulA() - { - var r = new SL2(); - r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12 - r[0][1] = this[0][0]; // r12 == t11 + public byte[] ToByteArray() + { + var buff = new byte[64]; + Array.Copy(this[0][0].ToByteArray(), 0, buff, 0, 16); + Array.Copy(this[0][1].ToByteArray(), 0, buff, 16, 16); + Array.Copy(this[1][0].ToByteArray(), 0, buff, 32, 16); + Array.Copy(this[1][1].ToByteArray(), 0, buff, 48, 16); + return buff; + } - r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22 - r[1][1] = this[1][0]; // r22 == t21 - - return r; - } - - // MulB() returns this*B, B = {{x, x+1}, {1, 1}} - public SL2 MulB() - { - var r = new SL2(); - r[0][0] = GF127.Mul10(this[0][0]) + this[0][1]; // r11 == t11*x + t12 - r[0][1] = GF127.Mul10(this[0][0]) + this[0][0] + this[0][1]; // r12 == t11*x + t11 + t12 - - r[1][0] = GF127.Mul10(this[1][0]) + this[1][1]; // r21 == t21*x + t22 - r[1][1] = GF127.Mul10(this[1][0]) + this[1][0] + this[1][1]; // r22 == t21*x + t21 + t22 - - return r; - } - - public SL2 FromByteArray(byte[] data) - { - if (data.Length != 64) - throw new ArgumentException(nameof(SL2) + $" invalid data, exect={64}, ecatual={data.Length}"); - this[0][0] = new GF127().FromByteArray(data[0..16]); - this[0][1] = new GF127().FromByteArray(data[16..32]); - this[1][0] = new GF127().FromByteArray(data[32..48]); - this[1][1] = new GF127().FromByteArray(data[48..64]); - return this; - } - - public byte[] ToByteArray() - { - var buff = new byte[64]; - Array.Copy(this[0][0].ToByteArray(), 0, buff, 0, 16); - Array.Copy(this[0][1].ToByteArray(), 0, buff, 16, 16); - Array.Copy(this[1][0].ToByteArray(), 0, buff, 32, 16); - Array.Copy(this[1][1].ToByteArray(), 0, buff, 48, 16); - return buff; - } - - public override string ToString() - { - return this[0][0].ToString() + this[0][1].ToString() + - this[1][0].ToString() + this[1][1].ToString(); - } + public override string ToString() + { + return this[0][0].ToString() + this[0][1].ToString() + + this[1][0].ToString() + this[1][1].ToString(); } } diff --git a/src/FrostFS.SDK.Cryptography/Tz/TzHash.cs b/src/FrostFS.SDK.Cryptography/Tz/TzHash.cs index e770631..7114bed 100644 --- a/src/FrostFS.SDK.Cryptography/Tz/TzHash.cs +++ b/src/FrostFS.SDK.Cryptography/Tz/TzHash.cs @@ -1,139 +1,140 @@ -using System.Security; -using System.Security.Cryptography; +//using System; +//using System.Collections.Generic; +//using System.Security; +//using System.Security.Cryptography; -namespace FrostFS.SDK.Cryptography.Tz -{ - public class TzHash : HashAlgorithm - { - private const int TzHashLength = 64; - private GF127[] x; - public override int HashSize => TzHashLength; +//namespace FrostFS.SDK.Cryptography.Tz; - public TzHash() - { - Initialize(); - } +//public class TzHash : HashAlgorithm +//{ +// private const int TzHashLength = 64; +// private GF127[] x; +// public override int HashSize => TzHashLength; - public override void Initialize() - { - x = new GF127[4]; - Reset(); - HashValue = null; - } - - public void Reset() - { - x[0] = new GF127(1, 0); - x[1] = new GF127(0, 0); - x[2] = new GF127(0, 0); - x[3] = new GF127(1, 0); - } +// public TzHash() +// { +// Initialize(); +// } - public byte[] ToByteArray() - { - var buff = new byte[HashSize]; - for (int i = 0; i < 4; i++) - { - Array.Copy(x[i].ToByteArray(), 0, buff, i * 16, 16); - } - return buff; - } +// public override void Initialize() +// { +// x = new GF127[4]; +// Reset(); +// HashValue = null; +// } + +// public void Reset() +// { +// x[0] = new GF127(1, 0); +// x[1] = new GF127(0, 0); +// x[2] = new GF127(0, 0); +// x[3] = new GF127(1, 0); +// } - [SecurityCritical] - protected override void HashCore(byte[] array, int ibStart, int cbSize) - { - _ = HashData(array[ibStart..(ibStart + cbSize)]); - } +// public byte[] ToByteArray() +// { +// var buff = new byte[HashSize]; +// for (int i = 0; i < 4; i++) +// { +// Array.Copy(x[i].ToByteArray(), 0, buff, i * 16, 16); +// } +// return buff; +// } - [SecurityCritical] - protected override byte[] HashFinal() - { - return HashValue = ToByteArray(); - } +// [SecurityCritical] +// protected override void HashCore(byte[] array, int ibStart, int cbSize) +// { +// _ = HashData(array[ibStart..(ibStart + cbSize)]); +// } - [SecurityCritical] - private int HashData(byte[] data) - { - var n = data.Length; - for (int i = 0; i < n; i++) - { - for (int j = 7; j >= 0; j--) - { - MulBitRight(ref x[0], ref x[1], ref x[2], ref x[3], (data[i] & (1 << j)) != 0); - } - } - return n; - } +// [SecurityCritical] +// protected override byte[] HashFinal() +// { +// return HashValue = ToByteArray(); +// } - // MulBitRight() multiply A (if the bit is 0) or B (if the bit is 1) on the right side - private void MulBitRight(ref GF127 c00, ref GF127 c01, ref GF127 c10, ref GF127 c11, bool bit) - { - // plan 1 - GF127 t; - if (bit) - { // MulB - t = c00; - c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01 - c01 = GF127.Mul11(t) + c01; // c01 = c00 * (x+1) + c01 +// [SecurityCritical] +// private int HashData(byte[] data) +// { +// var n = data.Length; +// for (int i = 0; i < n; i++) +// { +// for (int j = 7; j >= 0; j--) +// { +// MulBitRight(ref x[0], ref x[1], ref x[2], ref x[3], (data[i] & (1 << j)) != 0); +// } +// } +// return n; +// } - t = c10; - c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11 - c11 = GF127.Mul11(t) + c11; // c11 = c10 * (x+1) + c11 - } - else - { // MulA - t = c00; - c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01 - c01 = t; // c01 = c00 +// // MulBitRight() multiply A (if the bit is 0) or B (if the bit is 1) on the right side +// private void MulBitRight(ref GF127 c00, ref GF127 c01, ref GF127 c10, ref GF127 c11, bool bit) +// { +// // plan 1 +// GF127 t; +// if (bit) +// { // MulB +// t = c00; +// c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01 +// c01 = GF127.Mul11(t) + c01; // c01 = c00 * (x+1) + c01 - t = c10; - c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11 - c11 = t; // c11 = c10; - } +// t = c10; +// c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11 +// c11 = GF127.Mul11(t) + c11; // c11 = c10 * (x+1) + c11 +// } +// else +// { // MulA +// t = c00; +// c00 = GF127.Mul10(c00) + c01; // c00 = c00 * x + c01 +// c01 = t; // c01 = c00 - //// plan 2 - //var r = new SL2(c00, c01, c10, c11); - //if (bit) - // r.MulB(); - //else - // r.MulA(); - } +// t = c10; +// c10 = GF127.Mul10(c10) + c11; // c10 = c10 * x + c11 +// c11 = t; // c11 = c10; +// } - // Concat() performs combining of hashes based on homomorphic characteristic. - public static byte[] Concat(List hs) - { - var r = SL2.ID; - foreach (var h in hs) - { - r *= new SL2().FromByteArray(h); - } - return r.ToByteArray(); - } +// //// plan 2 +// //var r = new SL2(c00, c01, c10, c11); +// //if (bit) +// // r.MulB(); +// //else +// // r.MulA(); +// } - // Validate() checks if hashes in hs combined are equal to h. - public static bool Validate(byte[] h, List hs) - { - var expected = new SL2().FromByteArray(h); - var actual = new SL2().FromByteArray(Concat(hs)); - return expected.Equals(actual); - } +// // Concat() performs combining of hashes based on homomorphic characteristic. +// public static byte[] Concat(List hs) +// { +// var r = SL2.ID; +// foreach (var h in hs) +// { +// r *= new SL2().FromByteArray(h); +// } +// return r.ToByteArray(); +// } - // SubtractR() returns hash a, such that Concat(a, b) == c - public static byte[] SubstractR(byte[] b, byte[] c) - { - var t1 = new SL2().FromByteArray(b); - var t2 = new SL2().FromByteArray(c); - var r = t2 * SL2.Inv(t1); - return r.ToByteArray(); - } +// // Validate() checks if hashes in hs combined are equal to h. +// public static bool Validate(byte[] h, List hs) +// { +// var expected = new SL2().FromByteArray(h); +// var actual = new SL2().FromByteArray(Concat(hs)); +// return expected.Equals(actual); +// } - // SubtractL() returns hash b, such that Concat(a, b) == c - public static byte[] SubstractL(byte[] a, byte[] c) - { - var t1 = new SL2().FromByteArray(a); - var t2 = new SL2().FromByteArray(c); - var r = SL2.Inv(t1) * t2; - return r.ToByteArray(); - } - } -} +// // SubtractR() returns hash a, such that Concat(a, b) == c +// public static byte[] SubstractR(byte[] b, byte[] c) +// { +// var t1 = new SL2().FromByteArray(b); +// var t2 = new SL2().FromByteArray(c); +// var r = t2 * SL2.Inv(t1); +// return r.ToByteArray(); +// } + +// // SubtractL() returns hash b, such that Concat(a, b) == c +// public static byte[] SubstractL(byte[] a, byte[] c) +// { +// var t1 = new SL2().FromByteArray(a); +// var t2 = new SL2().FromByteArray(c); +// var r = SL2.Inv(t1) * t2; +// return r.ToByteArray(); +// } +//} diff --git a/src/FrostFS.SDK.Cryptography/UUID.cs b/src/FrostFS.SDK.Cryptography/UUID.cs index 3631c5e..656acaf 100644 --- a/src/FrostFS.SDK.Cryptography/UUID.cs +++ b/src/FrostFS.SDK.Cryptography/UUID.cs @@ -1,17 +1,24 @@ using Google.Protobuf; +using System; -namespace FrostFS.SDK.Cryptography +namespace FrostFS.SDK.Cryptography; + +public static class UUIDExtension { - public static class UUIDExtension + public static Guid ToUuid(this ByteString id) { - public static Guid ToUuid(this ByteString id) - { - return Guid.Parse(Convert.ToHexString(id.ToByteArray())); - } + return Guid.Parse(BitConverter.ToString(id.ToByteArray()).Replace("-", "")); + } + + public static byte[] ToBytes(this Guid id) + { + var str = id.ToString("N"); + var len = str.Length; + var bytes = new byte[len/2]; + + for (int i = 0; i < len; i += 2) + bytes[i/2] = Convert.ToByte(str.Substring(i, 2), 16); - public static byte[] ToBytes(this Guid id) - { - return Convert.FromHexString(id.ToString("N")); - } + return bytes; } } diff --git a/src/FrostFS.SDK.ModelsV2/Container.cs b/src/FrostFS.SDK.ModelsV2/Container.cs index 03f4783..d32ff8f 100644 --- a/src/FrostFS.SDK.ModelsV2/Container.cs +++ b/src/FrostFS.SDK.ModelsV2/Container.cs @@ -1,3 +1,5 @@ +using System; + using FrostFS.SDK.ModelsV2.Enums; using FrostFS.SDK.ModelsV2.Netmap; diff --git a/src/FrostFS.SDK.ModelsV2/ContainerId.cs b/src/FrostFS.SDK.ModelsV2/ContainerId.cs index fc2e9ee..8bfbc54 100644 --- a/src/FrostFS.SDK.ModelsV2/ContainerId.cs +++ b/src/FrostFS.SDK.ModelsV2/ContainerId.cs @@ -1,4 +1,6 @@ -using FrostFS.SDK.Cryptography; +using System; + +using FrostFS.SDK.Cryptography; namespace FrostFS.SDK.ModelsV2; @@ -10,16 +12,15 @@ public class ContainerId { Value = id; } - + public static ContainerId FromHash(byte[] hash) { if (hash.Length != Constants.Sha256HashLength) - { throw new FormatException("ContainerID must be a sha256 hash."); - } + return new ContainerId(Base58.Encode(hash)); } - + public byte[] ToHash() { return Base58.Decode(Value); diff --git a/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs b/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs index f22dd36..5c222fc 100644 --- a/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs +++ b/src/FrostFS.SDK.ModelsV2/Enums/BasicAcl.cs @@ -6,13 +6,13 @@ public enum BasicAcl { [Description("Basic ACL for private container")] Private = 0x1C8C8CCC, - + [Description("Basic ACL for public RO container")] PublicRO = 0x1FBF8CFF, - + [Description("Basic ACL for public RW container")] PublicRW = 0x1FBFBFFF, - + [Description("Basic ACL for public append container")] PublicAppend = 0x1FBF9FFF, } \ No newline at end of file diff --git a/src/FrostFS.SDK.ModelsV2/FrostFS.SDK.ModelsV2.csproj b/src/FrostFS.SDK.ModelsV2/FrostFS.SDK.ModelsV2.csproj index ba8c5fd..96a477c 100644 --- a/src/FrostFS.SDK.ModelsV2/FrostFS.SDK.ModelsV2.csproj +++ b/src/FrostFS.SDK.ModelsV2/FrostFS.SDK.ModelsV2.csproj @@ -1,13 +1,13 @@ - + - - net6.0 - enable - enable - + + netstandard2.0 + 12.0 + enable + - - - + + + diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs b/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs index d4960d7..b638bb6 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs +++ b/src/FrostFS.SDK.ModelsV2/Netmap/PlacementPolicy.cs @@ -2,8 +2,8 @@ namespace FrostFS.SDK.ModelsV2.Netmap; public class PlacementPolicy { - public Replica[] Replicas { get; init; } - public bool Unique { get; init; } + public Replica[] Replicas { get; private set; } + public bool Unique { get; private set; } public PlacementPolicy(bool unique, params Replica[] replicas) { diff --git a/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs b/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs index 2b5ee12..a6aeac9 100644 --- a/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs +++ b/src/FrostFS.SDK.ModelsV2/Netmap/Replica.cs @@ -8,7 +8,7 @@ public class Replica public Replica(int count, string? selector = null) { selector ??= string.Empty; - + Count = count; Selector = selector; } diff --git a/src/FrostFS.SDK.ModelsV2/Object.cs b/src/FrostFS.SDK.ModelsV2/Object.cs index cc859e5..7db6289 100644 --- a/src/FrostFS.SDK.ModelsV2/Object.cs +++ b/src/FrostFS.SDK.ModelsV2/Object.cs @@ -32,17 +32,17 @@ public class ObjectFilter { return new ObjectFilter(matchType, HeaderPrefix + "objectID", objectId.Value); } - + public static ObjectFilter OwnerFilter(ObjectMatchType matchType, OwnerId ownerId) { return new ObjectFilter(matchType, HeaderPrefix + "ownerID", ownerId.Value); } - + public static ObjectFilter RootFilter() { return new ObjectFilter(ObjectMatchType.Unspecified, HeaderPrefix + "ROOT", ""); } - + public static ObjectFilter VersionFilter(ObjectMatchType matchType, Version version) { return new ObjectFilter(matchType, HeaderPrefix + "version", version.ToString()); diff --git a/src/FrostFS.SDK.ModelsV2/ObjectId.cs b/src/FrostFS.SDK.ModelsV2/ObjectId.cs index 375e439..2bcf3ab 100644 --- a/src/FrostFS.SDK.ModelsV2/ObjectId.cs +++ b/src/FrostFS.SDK.ModelsV2/ObjectId.cs @@ -1,4 +1,6 @@ -using FrostFS.SDK.Cryptography; +using System; + +using FrostFS.SDK.Cryptography; namespace FrostFS.SDK.ModelsV2; @@ -10,7 +12,7 @@ public class ObjectId { Value = id; } - + public static ObjectId FromHash(byte[] hash) { if (hash.Length != Constants.Sha256HashLength) @@ -19,7 +21,7 @@ public class ObjectId } return new ObjectId(Base58.Encode(hash)); } - + public byte[] ToHash() { return Base58.Decode(Value); diff --git a/src/FrostFS.SDK.ModelsV2/OwnerId.cs b/src/FrostFS.SDK.ModelsV2/OwnerId.cs index d223be5..85cf239 100644 --- a/src/FrostFS.SDK.ModelsV2/OwnerId.cs +++ b/src/FrostFS.SDK.ModelsV2/OwnerId.cs @@ -1,4 +1,5 @@ using System.Security.Cryptography; + using FrostFS.SDK.Cryptography; namespace FrostFS.SDK.ModelsV2; @@ -16,7 +17,7 @@ public class OwnerId { return new OwnerId(key.PublicKey().PublicKeyToAddress()); } - + public byte[] ToHash() { return Base58.Decode(Value); diff --git a/src/FrostFS.SDK.ModelsV2/Status.cs b/src/FrostFS.SDK.ModelsV2/Status.cs index 4995742..2d56441 100644 --- a/src/FrostFS.SDK.ModelsV2/Status.cs +++ b/src/FrostFS.SDK.ModelsV2/Status.cs @@ -17,7 +17,7 @@ public class Status { return Code == StatusCode.Success; } - + public override string ToString() { return $"Response status: {Code}. Message: {Message}."; diff --git a/src/FrostFS.SDK.ProtosV2/FrostFS.SDK.ProtosV2.csproj b/src/FrostFS.SDK.ProtosV2/FrostFS.SDK.ProtosV2.csproj index 2100252..746a8b4 100644 --- a/src/FrostFS.SDK.ProtosV2/FrostFS.SDK.ProtosV2.csproj +++ b/src/FrostFS.SDK.ProtosV2/FrostFS.SDK.ProtosV2.csproj @@ -1,33 +1,32 @@ - + - - net6.0 - enable - enable - + + netstandard2.0 + 12.0 + enable + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + diff --git a/src/FrostFS.SDK.ProtosV2/Interfaces/IMetaHeader.cs b/src/FrostFS.SDK.ProtosV2/Interfaces/IMetaHeader.cs index 5db1515..68c428d 100644 --- a/src/FrostFS.SDK.ProtosV2/Interfaces/IMetaHeader.cs +++ b/src/FrostFS.SDK.ProtosV2/Interfaces/IMetaHeader.cs @@ -1,9 +1,8 @@ using Google.Protobuf; -namespace FrostFS.Session +namespace FrostFS.Session; + +public interface IMetaHeader : IMessage { - public interface IMetaHeader : IMessage - { - IMetaHeader GetOrigin(); - } + IMetaHeader GetOrigin(); } diff --git a/src/FrostFS.SDK.ProtosV2/Interfaces/IRequest.cs b/src/FrostFS.SDK.ProtosV2/Interfaces/IRequest.cs index 6c0b264..f75db43 100644 --- a/src/FrostFS.SDK.ProtosV2/Interfaces/IRequest.cs +++ b/src/FrostFS.SDK.ProtosV2/Interfaces/IRequest.cs @@ -1,8 +1,7 @@ -namespace FrostFS.Session +namespace FrostFS.Session; + +public interface IRequest : IVerificableMessage { - public interface IRequest : IVerificableMessage - { - RequestMetaHeader MetaHeader { get; set; } - RequestVerificationHeader VerifyHeader { get; set; } - } + RequestMetaHeader MetaHeader { get; set; } + RequestVerificationHeader VerifyHeader { get; set; } } diff --git a/src/FrostFS.SDK.ProtosV2/Interfaces/IResponse.cs b/src/FrostFS.SDK.ProtosV2/Interfaces/IResponse.cs index f9fa1bb..609be8e 100644 --- a/src/FrostFS.SDK.ProtosV2/Interfaces/IResponse.cs +++ b/src/FrostFS.SDK.ProtosV2/Interfaces/IResponse.cs @@ -1,8 +1,7 @@ -namespace FrostFS.Session +namespace FrostFS.Session; + +public interface IResponse : IVerificableMessage { - public interface IResponse : IVerificableMessage - { - ResponseMetaHeader MetaHeader { get; set; } - ResponseVerificationHeader VerifyHeader { get; set; } - } + ResponseMetaHeader MetaHeader { get; set; } + ResponseVerificationHeader VerifyHeader { get; set; } } diff --git a/src/FrostFS.SDK.ProtosV2/Interfaces/IVerifiableMessage.cs b/src/FrostFS.SDK.ProtosV2/Interfaces/IVerifiableMessage.cs index 3141874..3903757 100644 --- a/src/FrostFS.SDK.ProtosV2/Interfaces/IVerifiableMessage.cs +++ b/src/FrostFS.SDK.ProtosV2/Interfaces/IVerifiableMessage.cs @@ -1,13 +1,12 @@ using Google.Protobuf; -namespace FrostFS.Session +namespace FrostFS.Session; + +public interface IVerificableMessage : IMessage { - public interface IVerificableMessage : IMessage - { - IMetaHeader GetMetaHeader(); - void SetMetaHeader(IMetaHeader metaHeader); - IVerificationHeader GetVerificationHeader(); - void SetVerificationHeader(IVerificationHeader verificationHeader); - IMessage GetBody(); - } + IMetaHeader GetMetaHeader(); + void SetMetaHeader(IMetaHeader metaHeader); + IVerificationHeader GetVerificationHeader(); + void SetVerificationHeader(IVerificationHeader verificationHeader); + IMessage GetBody(); } diff --git a/src/FrostFS.SDK.ProtosV2/Interfaces/IVerificationHeader.cs b/src/FrostFS.SDK.ProtosV2/Interfaces/IVerificationHeader.cs index 19da0e2..6a637c3 100644 --- a/src/FrostFS.SDK.ProtosV2/Interfaces/IVerificationHeader.cs +++ b/src/FrostFS.SDK.ProtosV2/Interfaces/IVerificationHeader.cs @@ -1,14 +1,13 @@ using FrostFS.Refs; using Google.Protobuf; -namespace FrostFS.Session +namespace FrostFS.Session; + +public interface IVerificationHeader : IMessage { - public interface IVerificationHeader : IMessage - { - Signature BodySignature { get; set; } - Signature MetaSignature { get; set; } - Signature OriginSignature { get; set; } - IVerificationHeader GetOrigin(); - void SetOrigin(IVerificationHeader verificationHeader); - } + Signature BodySignature { get; set; } + Signature MetaSignature { get; set; } + Signature OriginSignature { get; set; } + IVerificationHeader GetOrigin(); + void SetOrigin(IVerificationHeader verificationHeader); } diff --git a/src/FrostFS.SDK.ProtosV2/container/Extension.Message.cs b/src/FrostFS.SDK.ProtosV2/container/Extension.Message.cs index 3c54a01..a46ddc2 100644 --- a/src/FrostFS.SDK.ProtosV2/container/Extension.Message.cs +++ b/src/FrostFS.SDK.ProtosV2/container/Extension.Message.cs @@ -1,397 +1,397 @@ -using FrostFS.Session; using Google.Protobuf; -namespace FrostFS.Container +using FrostFS.Session; + +namespace FrostFS.Container; + +public partial class AnnounceUsedSpaceRequest : IRequest { - public partial class AnnounceUsedSpaceRequest : IRequest + IMetaHeader IVerificableMessage.GetMetaHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return MetaHeader; } - public partial class AnnounceUsedSpaceResponse : IResponse + IVerificationHeader IVerificableMessage.GetVerificationHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return VerifyHeader; } - public partial class GetRequest : IRequest + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + MetaHeader = (RequestMetaHeader)metaHeader; } - public partial class GetResponse : IResponse + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + VerifyHeader = (RequestVerificationHeader)verificationHeader; } - public partial class PutRequest : IRequest + public IMessage GetBody() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class PutResponse : IResponse - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class DeleteRequest : IRequest - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class DeleteResponse : IResponse - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class ListRequest : IRequest - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class ListResponse : IResponse - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class SetExtendedACLRequest : IRequest - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class SetExtendedACLResponse : IResponse - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class GetExtendedACLRequest : IRequest - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } - } - - public partial class GetExtendedACLResponse : IResponse - { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return Body; + } +} + +public partial class AnnounceUsedSpaceResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class GetRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class GetResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class PutRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class PutResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class DeleteRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class DeleteResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class ListRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class ListResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class SetExtendedACLRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class SetExtendedACLResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class GetExtendedACLRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class GetExtendedACLResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; } } diff --git a/src/FrostFS.SDK.ProtosV2/netmap/Extension.Message.cs b/src/FrostFS.SDK.ProtosV2/netmap/Extension.Message.cs index 8ab7c04..207568d 100644 --- a/src/FrostFS.SDK.ProtosV2/netmap/Extension.Message.cs +++ b/src/FrostFS.SDK.ProtosV2/netmap/Extension.Message.cs @@ -1,117 +1,116 @@ using FrostFS.Session; using Google.Protobuf; -namespace FrostFS.Netmap +namespace FrostFS.Netmap; + +public partial class LocalNodeInfoRequest : IRequest { - public partial class LocalNodeInfoRequest : IRequest + IMetaHeader IVerificableMessage.GetMetaHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return MetaHeader; } - public partial class LocalNodeInfoResponse : IResponse + IVerificationHeader IVerificableMessage.GetVerificationHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return VerifyHeader; } - public partial class NetworkInfoRequest : IRequest + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + MetaHeader = (RequestMetaHeader)metaHeader; } - public partial class NetworkInfoResponse : IResponse + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + public IMessage GetBody() + { + return Body; + } +} + +public partial class LocalNodeInfoResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class NetworkInfoRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; + } +} + +public partial class NetworkInfoResponse : IResponse +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; } } diff --git a/src/FrostFS.SDK.ProtosV2/session/Extension.Message.cs b/src/FrostFS.SDK.ProtosV2/session/Extension.Message.cs index 9261865..fd78adc 100644 --- a/src/FrostFS.SDK.ProtosV2/session/Extension.Message.cs +++ b/src/FrostFS.SDK.ProtosV2/session/Extension.Message.cs @@ -1,60 +1,59 @@ using Google.Protobuf; -namespace FrostFS.Session +namespace FrostFS.Session; + +public partial class CreateResponse : IResponse { - public partial class CreateResponse : IResponse + IMetaHeader IVerificableMessage.GetMetaHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } - - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } - - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (ResponseMetaHeader)metaHeader; - } - - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (ResponseVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + return MetaHeader; } - public partial class CreateRequest : IRequest + IVerificationHeader IVerificableMessage.GetVerificationHeader() { - IMetaHeader IVerificableMessage.GetMetaHeader() - { - return MetaHeader; - } + return VerifyHeader; + } - IVerificationHeader IVerificableMessage.GetVerificationHeader() - { - return VerifyHeader; - } + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (ResponseMetaHeader)metaHeader; + } - void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) - { - MetaHeader = (RequestMetaHeader)metaHeader; - } + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (ResponseVerificationHeader)verificationHeader; + } - void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) - { - VerifyHeader = (RequestVerificationHeader)verificationHeader; - } - - public IMessage GetBody() - { - return Body; - } + public IMessage GetBody() + { + return Body; + } +} + +public partial class CreateRequest : IRequest +{ + IMetaHeader IVerificableMessage.GetMetaHeader() + { + return MetaHeader; + } + + IVerificationHeader IVerificableMessage.GetVerificationHeader() + { + return VerifyHeader; + } + + void IVerificableMessage.SetMetaHeader(IMetaHeader metaHeader) + { + MetaHeader = (RequestMetaHeader)metaHeader; + } + + void IVerificableMessage.SetVerificationHeader(IVerificationHeader verificationHeader) + { + VerifyHeader = (RequestVerificationHeader)verificationHeader; + } + + public IMessage GetBody() + { + return Body; } } diff --git a/src/FrostFS.SDK.ProtosV2/session/Extension.MetaHeader.cs b/src/FrostFS.SDK.ProtosV2/session/Extension.MetaHeader.cs index f653c7b..4fa4e72 100644 --- a/src/FrostFS.SDK.ProtosV2/session/Extension.MetaHeader.cs +++ b/src/FrostFS.SDK.ProtosV2/session/Extension.MetaHeader.cs @@ -1,18 +1,17 @@ -namespace FrostFS.Session -{ - public partial class RequestMetaHeader : IMetaHeader - { - public IMetaHeader GetOrigin() - { - return Origin; - } - } +namespace FrostFS.Session; - public partial class ResponseMetaHeader : IMetaHeader +public partial class RequestMetaHeader : IMetaHeader +{ + public IMetaHeader GetOrigin() { - public IMetaHeader GetOrigin() - { - return Origin; - } + return Origin; + } +} + +public partial class ResponseMetaHeader : IMetaHeader +{ + public IMetaHeader GetOrigin() + { + return Origin; } } diff --git a/src/FrostFS.SDK.ProtosV2/session/Extension.VerificationHeader.cs b/src/FrostFS.SDK.ProtosV2/session/Extension.VerificationHeader.cs index 8c994de..e991f3f 100644 --- a/src/FrostFS.SDK.ProtosV2/session/Extension.VerificationHeader.cs +++ b/src/FrostFS.SDK.ProtosV2/session/Extension.VerificationHeader.cs @@ -1,28 +1,27 @@ -namespace FrostFS.Session -{ - public partial class RequestVerificationHeader : IVerificationHeader - { - IVerificationHeader IVerificationHeader.GetOrigin() - { - return Origin; - } +namespace FrostFS.Session; - void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader) - { - Origin = (RequestVerificationHeader)verificationHeader; - } +public partial class RequestVerificationHeader : IVerificationHeader +{ + IVerificationHeader IVerificationHeader.GetOrigin() + { + return Origin; } - public partial class ResponseVerificationHeader : IVerificationHeader + void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader) { - IVerificationHeader IVerificationHeader.GetOrigin() - { - return Origin; - } - - void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader) - { - Origin = (ResponseVerificationHeader)verificationHeader; - } + Origin = (RequestVerificationHeader)verificationHeader; + } +} + +public partial class ResponseVerificationHeader : IVerificationHeader +{ + IVerificationHeader IVerificationHeader.GetOrigin() + { + return Origin; + } + + void IVerificationHeader.SetOrigin(IVerificationHeader verificationHeader) + { + Origin = (ResponseVerificationHeader)verificationHeader; } } diff --git a/src/FrostFS.SDK.ProtosV2/session/Extension.XHeader.cs b/src/FrostFS.SDK.ProtosV2/session/Extension.XHeader.cs index a49be70..f8f2695 100644 --- a/src/FrostFS.SDK.ProtosV2/session/Extension.XHeader.cs +++ b/src/FrostFS.SDK.ProtosV2/session/Extension.XHeader.cs @@ -1,9 +1,8 @@ -namespace FrostFS.Session +namespace FrostFS.Session; + +public partial class XHeader { - public partial class XHeader - { - public const string ReservedXHeaderPrefix = "__NEOFS__"; - public const string XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH"; - public const string XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH"; - } + public const string ReservedXHeaderPrefix = "__NEOFS__"; + public const string XHeaderNetmapEpoch = ReservedXHeaderPrefix + "NETMAP_EPOCH"; + public const string XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH"; }