// See file LICENSE for more information. library api.ecc; import 'dart:typed_data'; import 'package:pointycastle/api.dart'; import 'package:pointycastle/src/registry/registry.dart'; export 'ecdh.dart'; /// Standard ECC curve description abstract class ECDomainParameters { /// Get this domain's standard name. String get domainName; ECCurve get curve; List? get seed; ECPoint get G; BigInt get n; /// Create a curve description from its standard name factory ECDomainParameters(String domainName) => registry.create(domainName); } /// Type for coordinates of an [ECPoint] abstract class ECFieldElement { BigInt? toBigInteger(); String get fieldName; int get fieldSize; int get byteLength; ECFieldElement operator +(ECFieldElement b); ECFieldElement operator -(ECFieldElement b); ECFieldElement operator *(ECFieldElement b); ECFieldElement operator /(ECFieldElement b); ECFieldElement operator -(); ECFieldElement invert(); ECFieldElement square(); ECFieldElement? sqrt(); } /// An elliptic curve point abstract class ECPoint { ECCurve get curve; ECFieldElement? get x; ECFieldElement? get y; bool get isCompressed; bool get isInfinity; Uint8List getEncoded([bool compressed = true]); ECPoint? operator +(ECPoint? b); ECPoint? operator -(ECPoint b); ECPoint operator -(); ECPoint? twice(); /// Multiply this point by the given number [k]. ECPoint? operator *(BigInt? k); } /// An elliptic curve abstract class ECCurve { ECFieldElement? get a; ECFieldElement? get b; int get fieldSize; ECPoint? get infinity; /// Create an [ECFieldElement] on this curve from its big integer value. ECFieldElement fromBigInteger(BigInt x); /// Create an [ECPoint] on its curve from its coordinates ECPoint createPoint(BigInt x, BigInt y, [bool withCompression = false]); ECPoint decompressPoint(int yTilde, BigInt x1); /// Decode a point on this curve from its ASN.1 encoding. The different encodings are taken account of, including point /// compression for Fp (X9.62 s 4.2.1 pg 17). ECPoint? decodePoint(List encoded); } /// Base class for asymmetric keys in ECC abstract class ECAsymmetricKey implements AsymmetricKey { /// The domain parameters of this key final ECDomainParameters? parameters; /// Create an asymmetric key for the given domain parameters ECAsymmetricKey(this.parameters); } /// Private keys in ECC class ECPrivateKey extends ECAsymmetricKey implements PrivateKey { /// ECC's d private parameter final BigInt? d; /// Create an ECC private key for the given d and domain parameters. ECPrivateKey(this.d, ECDomainParameters? parameters) : super(parameters); @override bool operator ==(Object other) { if (other is! ECPrivateKey) return false; return (other.parameters == parameters) && (other.d == d); } @override int get hashCode { return parameters.hashCode + d.hashCode; } } /// Public keys in ECC class ECPublicKey extends ECAsymmetricKey implements PublicKey { /// ECC's Q public parameter final ECPoint? Q; /// Create an ECC public key for the given Q and domain parameters. ECPublicKey(this.Q, ECDomainParameters? parameters) : super(parameters); @override bool operator ==(Object other) { if (other is! ECPublicKey) return false; return (other.parameters == parameters) && (other.Q == Q); } @override int get hashCode { return parameters.hashCode + Q.hashCode; } } /// A [Signature] created with ECC. class ECSignature implements Signature { final BigInt r; final BigInt s; ECSignature(this.r, this.s); /// Returns true if s is in lower-s form, false otherwise. bool isNormalized(ECDomainParameters curveParams) { return !(s.compareTo(curveParams.n >> 1) > 0); } /// /// 'normalize' this signature by converting its s to lower-s form if necessary /// This is required to validate this signature with some libraries such as libsecp256k1 /// which enforce lower-s form for all signatures to combat ecdsa signature malleability /// /// Returns this if the signature was already normalized, or a copy if it is changed. /// ECSignature normalize(ECDomainParameters curveParams) { if (isNormalized(curveParams)) { return this; } return ECSignature(r, curveParams.n - s); } @override String toString() => '(${r.toString()},${s.toString()})'; @override bool operator ==(Object other) { if (other is! ECSignature) return false; return (other.r == r) && (other.s == s); } @override int get hashCode { return r.hashCode + s.hashCode; } } /// A pair of [ECPoint]s. class ECPair { final ECPoint x; final ECPoint y; const ECPair(this.x, this.y); @override bool operator ==(Object other) { if (other is! ECPair) return false; return (other.x == x) && (other.y == y); } @override int get hashCode => x.hashCode + y.hashCode * 37; } /// The encryptor using Elliptic Curve abstract class ECEncryptor { ECPair encrypt(ECPoint point); /// Initialize the encryptor. void init(CipherParameters params); } /// The decryptor using Elliptic Curve abstract class ECDecryptor { ECPoint decrypt(ECPair pair); /// Initialize the decryptor. void init(CipherParameters params); } abstract class ECDHAgreement { /// initialise the agreement engine. void init(ECPrivateKey param); /// return the field size for the agreement algorithm in bytes. int getFieldSize(); /// given a public key from a given party calculate the next /// message in the agreement sequence. BigInt calculateAgreement(ECPublicKey pubKey); }