236 lines
5.6 KiB
Dart
236 lines
5.6 KiB
Dart
// 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<int>? get seed;
|
||
|
||
ECPoint get G;
|
||
|
||
BigInt get n;
|
||
|
||
/// Create a curve description from its standard name
|
||
factory ECDomainParameters(String domainName) =>
|
||
registry.create<ECDomainParameters>(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<int> 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);
|
||
}
|