Initial
This commit is contained in:
		
							parent
							
								
									a39c5b0a6a
								
							
						
					
					
						commit
						9d1236a41a
					
				
							
								
								
									
										42
									
								
								Ed25519/Constants.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								Ed25519/Constants.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ed25519
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal static class Constants
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Compiler-time constants:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        internal const int BIT_LENGTH = 256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Run-time constants:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        internal static readonly BigInteger Q = BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819949");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger QM2 = BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819947");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger QP3 = BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819952");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger L = BigInteger.Parse("7237005577332262213973186563042994240857116359379907606001950938285454250989");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger D = BigInteger.Parse("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger I = BigInteger.Parse("19681161376707505956807079304988542015446066515923890162744021073123829784752");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger U_N = BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819967");
 | 
				
			||||||
 | 
					        internal static readonly BigInteger TWO = new BigInteger(2);
 | 
				
			||||||
 | 
					        internal static readonly BigInteger EIGHT = new BigInteger(8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Pre-calculated values:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        internal static readonly EdPoint B = new EdPoint
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            X = BigInteger.Parse("15112221349535400772501151409588531511454012693041857206046113283949847762202").Mod(Q),
 | 
				
			||||||
 | 
					            Y = BigInteger.Parse("46316835694926478169428394003475163141307993866256225615783033603165251855960").Mod(Q),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static readonly BigInteger RECOVER_X_EXP = Constants.QP3 / Constants.EIGHT;
 | 
				
			||||||
 | 
					        internal static readonly BigInteger TWO_POW_BIT_LENGTH_MINUS_TWO = BigInteger.Pow(2, BIT_LENGTH - 2);
 | 
				
			||||||
 | 
					        internal static readonly BigInteger[] TWO_POW_CACHE = Enumerable.Range(0, 2 * BIT_LENGTH).Select(i => BigInteger.Pow(2, i)).ToArray();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										101
									
								
								Ed25519/EdPoint.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								Ed25519/EdPoint.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ed25519
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    internal struct EdPoint
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public BigInteger X { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public BigInteger Y { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static EdPoint DecodePoint(ReadOnlySpan<byte> pointBytes)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var y = new BigInteger(pointBytes) & Constants.U_N;
 | 
				
			||||||
 | 
					            var x = y.RecoverX();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((x.IsEven ? 0 : 1) != pointBytes.GetBit(Constants.BIT_LENGTH - 1))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                x = Constants.Q - x;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var point = new EdPoint
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                X = x,
 | 
				
			||||||
 | 
					                Y = y,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!point.IsOnCurve())
 | 
				
			||||||
 | 
					                throw new ArgumentException("Decoding point that is not on curve");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return point;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ReadOnlySpan<byte> EncodePoint()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var nout = this.Y.EncodeInt();
 | 
				
			||||||
 | 
					            nout[^1] |= this.X.IsEven ? (byte)0 : (byte)0x80;
 | 
				
			||||||
 | 
					            return nout;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public EdPoint Edwards(EdPoint point2)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var xx12 = this.X * point2.X;
 | 
				
			||||||
 | 
					            var yy12 = this.Y * point2.Y;
 | 
				
			||||||
 | 
					            var dTemp = Constants.D * xx12 * yy12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var x3 = (this.X * point2.Y + point2.X * this.Y) * (1 + dTemp).Inv();
 | 
				
			||||||
 | 
					            var y3 = (this.Y * point2.Y + xx12) * (1 - dTemp).Inv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new EdPoint
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                X = x3.Mod(Constants.Q),
 | 
				
			||||||
 | 
					                Y = y3.Mod(Constants.Q),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public EdPoint ScalarMul(BigInteger e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (e.Equals(BigInteger.Zero))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new EdPoint
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    X = BigInteger.Zero,
 | 
				
			||||||
 | 
					                    Y = BigInteger.One,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var q = this.ScalarMul(e / Constants.TWO);
 | 
				
			||||||
 | 
					            q = q.EdwardsSquare();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return e.IsEven ? q : q.Edwards(this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public EdPoint EdwardsSquare()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var xx = this.X * this.X;
 | 
				
			||||||
 | 
					            var yy = this.Y * this.Y;
 | 
				
			||||||
 | 
					            var dTemp = Constants.D * xx * yy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var x3 = 2 * this.X * this.Y * (1 + dTemp).Inv();
 | 
				
			||||||
 | 
					            var y3 = (yy + xx) * (1 - dTemp).Inv();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new EdPoint
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                X = x3.Mod(Constants.Q),
 | 
				
			||||||
 | 
					                Y = y3.Mod(Constants.Q),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool IsOnCurve()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var xx = this.X * this.X;
 | 
				
			||||||
 | 
					            var yy = this.Y * this.Y;
 | 
				
			||||||
 | 
					            var dxxyy = Constants.D * yy * xx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return (yy - xx - dxxyy - 1).Mod(Constants.Q).Equals(BigInteger.Zero);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										107
									
								
								Ed25519/Extensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								Ed25519/Extensions.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using System.Security.Cryptography;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ed25519
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class Extensions
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        internal static ReadOnlySpan<byte> ComputeHash(this ReadOnlySpan<byte> data)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            using var sha512 = SHA512.Create();
 | 
				
			||||||
 | 
					            return sha512.ComputeHash(data.ToArray());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static ReadOnlySpan<byte> ComputeHash(this Stream inputStream)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            using var sha512 = SHA512.Create();
 | 
				
			||||||
 | 
					            return sha512.ComputeHash(inputStream);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger Mod(this BigInteger number, BigInteger modulo)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var result = number % modulo;
 | 
				
			||||||
 | 
					            return result < 0 ? result + modulo : result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger Inv(this BigInteger number)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return number.ExpMod(2, Constants.Q);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger RecoverX(this BigInteger y)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var y2 = y * y;
 | 
				
			||||||
 | 
					            var xx = (y2 - 1) * (Constants.D * y2 + 1).Inv();
 | 
				
			||||||
 | 
					            var x = xx.ExpMod(Constants.RECOVER_X_EXP, Constants.Q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!(x * x - xx).Mod(Constants.Q).Equals(BigInteger.Zero))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                x = (x * Constants.I).Mod(Constants.Q);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!x.IsEven)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                x = Constants.Q - x;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return x;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger ExpMod(this BigInteger number, BigInteger exponent, BigInteger modulo)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (exponent.Equals(BigInteger.Zero))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return BigInteger.One;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var result = BigInteger.Pow(number.ExpMod(exponent / Constants.TWO, modulo), 2).Mod(modulo);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (exponent.IsEven)
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            result *= number;
 | 
				
			||||||
 | 
					            result = result.Mod(modulo);
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static Span<byte> EncodeInt(this BigInteger number)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var nin = number.ToByteArray();
 | 
				
			||||||
 | 
					            var nout = new byte[Math.Max(nin.Length, 32)];
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Array.Copy(nin, nout, nin.Length);
 | 
				
			||||||
 | 
					            return nout;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger DecodeInt(this ReadOnlySpan<byte> data)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return new BigInteger(data) & Constants.U_N;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static BigInteger HashInt(this MemoryStream data)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var hash = data.ComputeHash();
 | 
				
			||||||
 | 
					            var hashSum = BigInteger.Zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (var i = 0; i < 2 * Constants.BIT_LENGTH; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var bit = hash.GetBit(i);
 | 
				
			||||||
 | 
					                if (bit != 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    hashSum += Constants.TWO_POW_CACHE[i];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return hashSum;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal static int GetBit(this ReadOnlySpan<byte> data, int index)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return data[index / 8] >> (index % 8) & 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										90
									
								
								Ed25519/Signer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								Ed25519/Signer.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Numerics;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Ed25519
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class Signer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static ReadOnlySpan<byte> Sign(ReadOnlySpan<byte> message, ReadOnlySpan<byte> privateKey, ReadOnlySpan<byte> publicKey)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var privateKeyHash = privateKey.ComputeHash();
 | 
				
			||||||
 | 
					            var privateKeyBits = Constants.TWO_POW_BIT_LENGTH_MINUS_TWO;
 | 
				
			||||||
 | 
					            for (var i = 3; i < Constants.BIT_LENGTH - 2; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var bit = privateKeyHash.GetBit(i);
 | 
				
			||||||
 | 
					                if (bit != 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    privateKeyBits += Constants.TWO_POW_CACHE[i];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BigInteger r;
 | 
				
			||||||
 | 
					            using (var rSub = new MemoryStream((Constants.BIT_LENGTH / 8) + message.Length))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                rSub.Write(privateKeyHash[(privateKeyHash.Length/2)..]);
 | 
				
			||||||
 | 
					                rSub.Write(message);
 | 
				
			||||||
 | 
					                rSub.Flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                r = rSub.HashInt();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var bigR = Constants.B.ScalarMul(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BigInteger s;
 | 
				
			||||||
 | 
					            var encodedBigR = bigR.EncodePoint();
 | 
				
			||||||
 | 
					            using (var sTemp = new MemoryStream(encodedBigR.Length + publicKey.Length + message.Length))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                sTemp.Write(encodedBigR);
 | 
				
			||||||
 | 
					                sTemp.Write(publicKey);
 | 
				
			||||||
 | 
					                sTemp.Write(message);
 | 
				
			||||||
 | 
					                sTemp.Flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                s = (r + sTemp.HashInt() * privateKeyBits).Mod(Constants.L);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using (var nOut = new MemoryStream(64))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                nOut.Write(encodedBigR);
 | 
				
			||||||
 | 
					                nOut.Write(s.EncodeInt());
 | 
				
			||||||
 | 
					                return nOut.ToArray();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static bool Validate(ReadOnlySpan<byte> signature, ReadOnlySpan<byte> message, ReadOnlySpan<byte> publicKey)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (signature.Length != Constants.BIT_LENGTH / 4)
 | 
				
			||||||
 | 
					                throw new ArgumentException("Signature length is wrong");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (publicKey.Length != Constants.BIT_LENGTH / 8)
 | 
				
			||||||
 | 
					                throw new ArgumentException("Public key length is wrong");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var signatureSliceLeft = signature[..(Constants.BIT_LENGTH / 8)];
 | 
				
			||||||
 | 
					            var pointSignatureLeft = EdPoint.DecodePoint(signatureSliceLeft);
 | 
				
			||||||
 | 
					            var pointPublicKey = EdPoint.DecodePoint(publicKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var signatureSliceRight = signature[(signature.Length/2)..];
 | 
				
			||||||
 | 
					            var signatureRight = signatureSliceRight.DecodeInt();
 | 
				
			||||||
 | 
					            var encodedSignatureLeftPoint = pointSignatureLeft.EncodePoint();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BigInteger h;
 | 
				
			||||||
 | 
					            using (var sTemp = new MemoryStream(encodedSignatureLeftPoint.Length + publicKey.Length + message.Length))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                sTemp.Write(encodedSignatureLeftPoint);
 | 
				
			||||||
 | 
					                sTemp.Write(publicKey);
 | 
				
			||||||
 | 
					                sTemp.Write(message);
 | 
				
			||||||
 | 
					                sTemp.Flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                h = sTemp.HashInt();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var ra = Constants.B.ScalarMul(signatureRight);
 | 
				
			||||||
 | 
					            var ah = pointPublicKey.ScalarMul(h);
 | 
				
			||||||
 | 
					            var rb = pointSignatureLeft.Edwards(ah);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return ra.X.Equals(rb.X) && ra.Y.Equals(rb.Y);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user