Beispiel #1
0
 public EcPoint(EcPoint p)
 {
     A         = p.A;
     B         = p.B;
     X         = p.X;
     Y         = p.Y;
     FieldChar = p.FieldChar;
 }
Beispiel #2
0
        //умножение точки на число.
        public static EcPoint Multiply(EcPoint p, BigInteger c)
        {
            EcPoint res = p;

            c = c - 1;
            while (c != 0)
            {
                if (c % 2 != 0)
                {
                    res = (res.X == p.X || res.Y == p.Y) ? Doubling(res) : res + p;
                    c--;
                }

                c /= 2;
                p  = Doubling(p);
            }

            return(res);
        }
Beispiel #3
0
        //сложение пары точек.
        public static EcPoint operator +(EcPoint p1, EcPoint p2)
        {
            var res = new EcPoint
            {
                A         = p1.A,
                B         = p1.B,
                FieldChar = p1.FieldChar
            };

            BigInteger dx = p2.X - p1.X;
            BigInteger dy = p2.Y - p1.Y;

            if (dx < 0)
            {
                dx += p1.FieldChar;
            }
            if (dy < 0)
            {
                dy += p1.FieldChar;
            }

            BigInteger t = (dy * dx.modInverse(p1.FieldChar)) % p1.FieldChar;

            if (t < 0)
            {
                t += p1.FieldChar;
            }

            res.X = (t * t - p1.X - p2.X) % p1.FieldChar;
            res.Y = (t * (p1.X - res.X) - p1.Y) % p1.FieldChar;

            if (res.X < 0)
            {
                res.X += p1.FieldChar;
            }
            if (res.Y < 0)
            {
                res.Y += p1.FieldChar;
            }

            return(res);
        }
Beispiel #4
0
        //удвоение точки.
        public static EcPoint Doubling(EcPoint p)
        {
            var res = new EcPoint
            {
                A         = p.A,
                B         = p.B,
                FieldChar = p.FieldChar
            };

            BigInteger dx = 2 * p.Y;
            BigInteger dy = 3 * p.X * p.X + p.A;

            if (dx < 0)
            {
                dx += p.FieldChar;
            }
            if (dy < 0)
            {
                dy += p.FieldChar;
            }

            BigInteger t = (dy * dx.modInverse(p.FieldChar)) % p.FieldChar;

            res.X = (t * t - p.X - p.X) % p.FieldChar;
            res.Y = (t * (p.X - res.X) - p.Y) % p.FieldChar;

            if (res.X < 0)
            {
                res.X += p.FieldChar;
            }
            if (res.Y < 0)
            {
                res.Y += p.FieldChar;
            }

            return(res);
        }
Beispiel #5
0
        public (SM2DeriveBytes?Key, byte[] Verifier, byte[] PeerVerifier) DeriveKey(
            EcPoint peerPubKey, EcPoint peerR, ReadOnlySpan <byte> peerIdent)
        {
            if (!_ephemeralKey.Param.Curve.ValidatePoint(peerPubKey))
            {
                throw new CryptographicException();
            }

            if (!_ephemeralKey.Param.Curve.ValidatePoint(peerR))
            {
                throw new CryptographicException();
            }

            var pkBytes = (_ephemeralKey.Param.Curve.BitLength + 7) / 8;

            var zPeer = SM2.ZValue(_ephemeralKey.Param, _hash, peerIdent, peerPubKey);
            var w     = _ephemeralKey.Param.BitLength;

            if (_ephemeralKey.Param.N.IsPowerOfTwo)
            {
                w -= 1;
            }
            w = (ushort)((w >> 1) + (w & 1) - 1);
            var w2 = (BigInteger)1 << w;
            var x2 = w2 + (_ephemeralKey.Q.X & (w2 - 1));
            var t  = (_privateKey + x2 * _ephemeralKey.D) % _ephemeralKey.Param.N;
            var x1 = w2 + (peerR.X & (w2 - 1));

            var vi = _ephemeralKey.Param.Curve.MultiplyAndAdd(1, peerPubKey, x1, peerR, _rng);
            var v  = _ephemeralKey.Param.Curve.ToAffine(_ephemeralKey.Param.Curve.Multiply(_ephemeralKey.Param.H * t, vi, _rng));

            if (v.Inf)
            {
                return(null, null !, null !);
            }

            var za  = _responder ? zPeer : _zValue;
            var zb  = _responder ? _zValue : zPeer;
            var zl  = za.Length + zb.Length;
            var key = new byte[pkBytes * 2 + zl];
            var xv  = v.X.ToByteArrayUBe(pkBytes);
            var yv  = v.Y.ToByteArrayUBe(pkBytes);

            xv.CopyTo(key, 0);
            yv.CopyTo(key, pkBytes);
            za.CopyTo(key, pkBytes * 2);
            zb.CopyTo(key, pkBytes * 2 + za.Length);

            var kdf = new SM2DeriveBytes(key, _hash);

            var ra = _responder ? peerR : _ephemeralKey.Q;
            var rb = _responder ? _ephemeralKey.Q : peerR;

#if NETSTANDARD2_0 || NETSTANDARD2_1
            _hash.Initialize();
            _hash.TransformBlock(xv, 0, pkBytes, null, 0);
            _hash.TransformBlock(za, 0, za.Length, null, 0);
            _hash.TransformBlock(zb, 0, zb.Length, null, 0);
            _hash.TransformBlock(ra.X.ToByteArrayUBe(pkBytes), 0, pkBytes, null, 0);
            _hash.TransformBlock(ra.Y.ToByteArrayUBe(pkBytes), 0, pkBytes, null, 0);
            _hash.TransformBlock(rb.X.ToByteArrayUBe(pkBytes), 0, pkBytes, null, 0);
            _hash.TransformFinalBlock(rb.Y.ToByteArrayUBe(pkBytes), 0, pkBytes);
            var si = _hash.Hash;

            _hash.Initialize();
            key[0] = 2;
            _hash.TransformBlock(key, 0, 1, null, 0);
            _hash.TransformBlock(yv, 0, pkBytes, null, 0);
            _hash.TransformFinalBlock(si, 0, si.Length);
            var sb = _hash.Hash;

            _hash.Initialize();
            key[0] = 3;
            _hash.TransformBlock(key, 0, 1, null, 0);
            _hash.TransformBlock(yv, 0, pkBytes, null, 0);
            _hash.TransformFinalBlock(si, 0, si.Length);
            var sa = _hash.Hash;
#else
            var sib = ArrayPool <byte> .Shared.Rent(pkBytes * 5 + zl);

            xv.CopyTo(sib, 0);
            za.CopyTo(sib, pkBytes);
            zb.CopyTo(sib, pkBytes + za.Length);
            ra.X.ToByteArrayUBe(pkBytes).CopyTo(sib, zl + pkBytes);
            ra.Y.ToByteArrayUBe(pkBytes).CopyTo(sib, zl + pkBytes * 2);
            rb.X.ToByteArrayUBe(pkBytes).CopyTo(sib, zl + pkBytes * 3);
            rb.Y.ToByteArrayUBe(pkBytes).CopyTo(sib, zl + pkBytes * 4);
            var si = _hash.ComputeHash(sib, 0, pkBytes * 5 + zl);
            ArrayPool <byte> .Shared.Return(sib);

            var sbb = ArrayPool <byte> .Shared.Rent(pkBytes + si.Length + 1);

            yv.CopyTo(sbb, 1);
            si.CopyTo(sbb, pkBytes + 1);
            sbb[0] = 2;
            var sb = _hash.ComputeHash(sbb, 0, pkBytes + si.Length + 1);

            sbb[0] = 3;
            var sa = _hash.ComputeHash(sbb, 0, pkBytes + si.Length + 1);
            ArrayPool <byte> .Shared.Return(sbb);
#endif

            return(kdf, _responder ? sb : sa, _responder ? sa : sb);
        }