public EccPoint Add(EccPoint pointA, EccPoint pointB) { // Any point added to infinity is itself if (pointA.Infinity) { return(pointB); } // Any point added to infinity is itself if (pointB.Infinity) { return(pointA); } // Any point added to its inverse is infinity if (pointA.Equals(Negate(pointB))) { return(new EccPoint("infinity")); } // Cannot add two identical points, use Double instead if (pointA.Equals(pointB)) { return(Double(pointA)); } var numerator = _operator.Subtract(pointB.Y, pointA.Y); var denominator = _operator.Subtract(pointB.X, pointA.X); var lambda = _operator.Divide(numerator, denominator); var x = _operator.Subtract(_operator.Subtract(_operator.Multiply(lambda, lambda), pointA.X), pointB.X); var y = _operator.Subtract(_operator.Multiply(_operator.Subtract(pointA.X, x), lambda), pointA.Y); return(new EccPoint(x, y)); }
/// <summary> /// Based on the Fixed-base comb method (Algorithm 17 from https://link.springer.com/content/pdf/10.1007/3-540-44499-8_1.pdf) /// </summary> /// <param name="scalar"></param> /// <returns></returns> private EccPoint FastMultiply(BigInteger scalar) { var width = 4; var degree = FieldSizeQ.ExactBitLength(); var d = degree.CeilingDivide(width); var scalarBits = new BitString(scalar, degree).Bits; var point = new EccPoint("infinity"); for (var i = d - 1; i >= 0; i--) { point = Double(point); var index = 0; for (var j = width - 1; j >= 0; j--) { index *= 2; if (i + d * j >= degree) { continue; } if (scalarBits[i + d * j]) { index++; } } if (index != 0) { point = Add(point, _precomputedMultiplication[index]); } } return(point); }
public bool PointExistsOnCurve(EccPoint point) { if (point.Infinity) { return(true); } // Point is out of bounds if (!PointExistsInField(point)) { return(false); } var ySquared = _operator.Multiply(point.Y, point.Y); var xTimesY = _operator.Multiply(point.X, point.Y); var lhs = _operator.Add(ySquared, xTimesY); var xCubed = _operator.Multiply(_operator.Multiply(point.X, point.X), point.X); var xSquared = _operator.Multiply(point.X, point.X); var aTimesXSquares = _operator.Multiply(CoefficientA, xSquared); var rhs = _operator.Add(_operator.Add(xCubed, aTimesXSquares), CoefficientB); // y^2 + xy = x^3 + ax^2 + b return(lhs == rhs); }
public static bool PerformEccPublicKeyValidation(IEccCurve curve, EccPoint publicKey, bool shouldThrow = false) { if (!curve.PointExistsOnCurve(publicKey)) { if (shouldThrow) { throw new Exception("public key does not exist on curve"); } return(false); } var n = curve.OrderN; var nQ = curve.Multiply(publicKey, n); if (!nQ.Infinity) { if (shouldThrow) { throw new Exception("public key validation error"); } return(false); } return(true); }
public EccPoint Negate(EccPoint point) { if (point.Infinity) { return(point); } return(new EccPoint(point.X, _operator.Add(point.X, point.Y))); }
public EccPoint Subtract(EccPoint pointA, EccPoint pointB) { if (pointA.Infinity || pointB.Infinity) { return(pointA); } return(Add(pointA, Negate(pointB))); }
public EccPoint Negate(EccPoint point) { if (point.Infinity) { return(point); } // Negate the point, - (x, y) == (x, -y), but -1 * y (mod q) == q - y return(new EccPoint(point.X, _operator.Negate(point.Y))); }
public PrimeCurve(Curve curveName, BigInteger p, BigInteger b, EccPoint g, BigInteger n) { CurveName = curveName; FieldSizeQ = p; CoefficientB = b; BasePointG = g; OrderN = n; _operator = new PrimeFieldOperator(p); }
void EcdhSample(Tpm2 tpm, TestContext testCtx) { // // Peer A (e.g. local machine): // // Template for an ECC key with the ECDH scheme: var inPub = new TpmPublic(TpmAlgId.Sha256, ObjectAttr.Decrypt | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, null, new EccParms(new SymDefObject(), new SchemeEcdh(TpmAlgId.Sha256), EccCurve.NistP256, new NullKdfScheme()), new EccPoint()); // Boilerplate stuff var pcrSel = new PcrSelection[0]; CreationData crData; byte[] crHash; TkCreation crTk; // Create a key for ECDH TpmPublic pubA; TpmHandle hKeyA = tpm.CreatePrimary(TpmRh.Owner, new SensitiveCreate(), inPub, null, new PcrSelection[0], out pubA, out crData, out crHash, out crTk); // // Peer B (e.g. remote machine): // // Receives 'pubA' from peer A // Load public key TpmHandle hPubKeyA = tpm.LoadExternal(null, pubA, TpmRh.Owner); // Create shared secret 'zB', and a public ECC point for exchange EccPoint ephPubPt; EccPoint zB = tpm.EcdhKeyGen(hPubKeyA, out ephPubPt); tpm.FlushContext(hPubKeyA); // // Peer A again: // // Receives 'ephPubPt' from peer B // A full key is required here EccPoint zA = tpm.EcdhZGen(hKeyA, ephPubPt); testCtx.AssertEqual("SharedSecret", zA, zB); tpm.FlushContext(hKeyA); } // EcdhSample
public bool PointExistsInField(EccPoint point) { var m = FieldSizeQ.ExactBitLength(); if (point.X.ExactBitLength() == m || point.Y.ExactBitLength() == m) { return(false); } return(true); }
public BinaryCurve(Curve curveName, BigInteger f, BigInteger a, BigInteger b, EccPoint basis, BigInteger n, int h, List <EccPoint> points = null) { CurveName = curveName; FieldSizeQ = f; CoefficientA = a; CoefficientB = b; BasePointG = basis; OrderN = n; CofactorH = h; _operator = new GaloisFieldOperator(f); _precomputedMultiplication = points ?? new List <EccPoint>(); }
public bool PointExistsInField(EccPoint point) { if (point.X < 0 || point.X > FieldSizeQ - 1) { return(false); } if (point.Y < 0 || point.Y > FieldSizeQ - 1) { return(false); } return(true); }
public EccPoint Multiply(EccPoint startPoint, BigInteger scalar) { // Intentional normal modulo, this is what CAVS does scalar %= OrderN; if (startPoint.Equals(BasePointG) && HasPrecomputedValues) { return(FastMultiply(scalar)); } else { return(Multiply(startPoint, new NonAdjacentBitString(scalar))); } }
public EccPoint Double(EccPoint point) { if (point.X == 0 || point.Infinity) { return(point); } var numerator = point.Y; var denominator = point.X; var lambda = _operator.Add(_operator.Multiply(numerator, _operator.Inverse(denominator)), point.X); var x = _operator.Add(_operator.Add(_operator.Multiply(lambda, lambda), lambda), CoefficientA); var y = _operator.Add(_operator.Multiply(_operator.Add(lambda, 1), x), _operator.Multiply(point.X, point.X)); return(new EccPoint(x, y)); }
public bool PointExistsOnCurve(EccPoint point) { if (point.Infinity) { return(true); } // Point is out of bounds if (!PointExistsInField(point)) { return(false); } var lhs = _operator.Multiply(point.Y, point.Y); var rhs = _operator.Add(_operator.Add(_operator.Multiply(_operator.Multiply(point.X, point.X), point.X), _operator.Multiply(CoefficientA, point.X)), CoefficientB); return(lhs == rhs); }
public EccPoint Add(EccPoint pointA, EccPoint pointB) { // Any point added to infinity is itself if (pointA.Infinity) { return(pointB); } // Any point added to infinity is itself if (pointB.Infinity) { return(pointA); } // Any point added to its inverse is infinity if (pointA.Equals(Negate(pointB))) { return(new EccPoint("infinity")); } // Cannot add two identical points, use Double instead if (pointA.Equals(pointB)) { return(Double(pointA)); } var numerator = _operator.Add(pointA.Y, pointB.Y); var denominator = _operator.Add(pointA.X, pointB.X); if (denominator == 0) { return(new EccPoint("infinity")); } var lambda = _operator.Multiply(numerator, _operator.Inverse(denominator)); // x = lambda * lambda + lambda + x1 + x2 + a var x = _operator.Add(_operator.Add(_operator.Add(_operator.Add(_operator.Multiply(lambda, lambda), lambda), pointA.X), pointB.X), CoefficientA); // y = lambda * (x1 + x3) + x + y1 var y = _operator.Add(_operator.Add(_operator.Multiply(_operator.Add(pointA.X, x), lambda), x), pointA.Y); return(new EccPoint(x, y)); }
public static SchemeEcdaa PrepareEcdaaScheme(Tpm2 tpm, TpmHandle signKey, ISigSchemeUnion scheme) { var schemeEcdaa = scheme as SchemeEcdaa; if (schemeEcdaa != null) { byte[] name, qualName; var keyPub = tpm.ReadPublic(signKey, out name, out qualName); ushort counter = 0; EccPoint l, E; EccPoint PP = keyPub.unique as EccPoint; tpm.Commit(signKey, PP, null, null, out l, out E, out counter); schemeEcdaa.count = counter; } return(schemeEcdaa); }
private EccPoint Multiply(EccPoint startPoint, NonAdjacentBitString nafBs) { var point = new EccPoint("infinity"); var naBits = nafBs.Bits; for (var i = naBits.Length - 1; i >= 0; i--) { point = Double(point); if (naBits[i] == 1) { point = Add(point, startPoint); } else if (naBits[i] == -1) { point = Subtract(point, startPoint); } } return(point); }
public EccPoint Double(EccPoint point) { if ((point.X == 0 && point.Y == 0) || point.Infinity) { return(point); } if (point.Y == 0) { throw new ArgumentException("Cannot double a point with y = 0"); } var numerator = _operator.Add(_operator.Multiply(_operator.Multiply(3, point.X), point.X), CoefficientA); var denominator = _operator.Multiply(2, point.Y); var lambda = _operator.Divide(numerator, denominator); var x = _operator.Subtract(_operator.Multiply(lambda, lambda), _operator.Multiply(2, point.X)); var y = _operator.Subtract(_operator.Multiply(_operator.Subtract(point.X, x), lambda), point.Y); return(new EccPoint(x, y)); }
public EccPoint Multiply(EccPoint startPoint, BigInteger scalar) { // Find scalar within group and convert to NABS, normal modulo here, not on the field, like CAVS return(Multiply(startPoint, new NonAdjacentBitString(scalar % OrderN))); }
public void ShouldReturnExpectedValidationResultEcc(string label, Curve curveEnum, EccPoint publicKey, bool shouldPassValidation) { var curve = new EccCurveFactory().GetCurve(curveEnum); var result = KeyValidationHelper.PerformEccPublicKeyValidation(curve, publicKey, false); Assert.AreEqual(shouldPassValidation, result); }
public EccPoint Subtract(EccPoint pointA, EccPoint pointB) { return(Add(pointA, Negate(pointB))); }