Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/src/cdsa/cdsa.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export 'curve_points.dart';
export 'curve_type.dart';
export 'curves.dart';
export 'ecdsa/ecdsa.dart';
export 'eddsa/eddsa.dart';
11 changes: 11 additions & 0 deletions lib/src/cdsa/curve_points.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,15 @@ class CurvePoints {
z: BigInt.one,
);
}

static EDPoint get generatorED25519 {
return EDPoint(
curve: Curves.ed25519,
n: BigInt.parse('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
x: BigInt.parse('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
y: BigInt.parse('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
z: BigInt.one,
t: BigInt.parse('46827403850823179245072216630277197565144205554125654976674165829533817101731'),
);
}
}
1 change: 1 addition & 0 deletions lib/src/cdsa/curve_type.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
enum CurveType {
secp256k1,
ed25519,
}
9 changes: 9 additions & 0 deletions lib/src/cdsa/curves.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ class Curves {
p: BigInt.parse('115792089237316195423570985008687907853269984665640564039457584007908834671663'),
);
}

static EDCurve get ed25519 {
return EDCurve(
a: BigInt.from(-1),
d: BigInt.parse('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
h: BigInt.from(8),
p: BigInt.parse('57896044618658097711785492504343953926634992332820282019728792003956564819949'),
);
}
}
37 changes: 37 additions & 0 deletions lib/src/cdsa/eddsa/ed25519/ed25519_private_key.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'dart:typed_data';

import 'package:cryptography_utils/cryptography_utils.dart';

/// [ED25519PrivateKey] represents [EDPrivateKey] constructed with specific Curve (ED25519) and chain code.
class ED25519PrivateKey extends ABip32PrivateKey {
/// Returns the length of the private key.
static const int _length = 32;

/// EdDSA Private key used for cryptographic operations, following the ED25519 curve specification.
final EDPrivateKey edPrivateKey;

const ED25519PrivateKey({
required super.metadata,
required this.edPrivateKey,
});

/// Returns the private key as a byte array.
@override
Uint8List get bytes => edPrivateKey.bytes;

/// Returns the length of the private key.
@override
int get length => _length;

/// Returns the public key derived from the private key.
@override
ED25519PublicKey get publicKey {
return ED25519PublicKey(
edPublicKey: edPrivateKey.edPublicKey,
metadata: metadata,
);
}

@override
List<Object?> get props => <Object>[edPrivateKey, metadata];
}
33 changes: 33 additions & 0 deletions lib/src/cdsa/eddsa/ed25519/ed25519_public_key.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'dart:typed_data';

import 'package:cryptography_utils/cryptography_utils.dart';

/// [ED25519PublicKey] represents [EDPublicKey] constructed with specific Curve (ED25519) and chain code.
class ED25519PublicKey extends ABip32PublicKey {
/// EdDSA public key derived from the corresponding private key, following the ED25519 curve specification.
/// This public key is used in the verification process of digital signatures, allowing others to verify the authenticity
/// of transactions or messages signed with the associated private key, without compromising the private key itself.
final EDPublicKey edPublicKey;

const ED25519PublicKey({
required super.metadata,
required this.edPublicKey,
});

/// Returns the compressed form of the public key.
@override
Uint8List get compressed => bytes;

/// Returns the uncompressed form of the public key.
@override
Uint8List get uncompressed => bytes;

/// Returns the public key as bytes.
Uint8List get bytes => edPublicKey.bytes;

/// Returns the length of the public key.
int get length => edPublicKey.length;

@override
List<Object?> get props => <Object?>[edPublicKey];
}
69 changes: 69 additions & 0 deletions lib/src/cdsa/eddsa/ed25519/signer/ed25519_signer.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Class was shaped by the influence of several key sources including:
// "blockchain_utils" Copyright (c) 2010 Mohsen
// https://github.com/mrtnetwork/blockchain_utils/.
//
// BSD 3-Clause License
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import 'dart:typed_data';

import 'package:cryptography_utils/cryptography_utils.dart';
import 'package:cryptography_utils/src/cdsa/eddsa/ed25519/signer/ed_signature.dart';
import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart';
import 'package:cryptography_utils/src/utils/big_int_utils.dart';

/// This class implements the functionality necessary to generate digital signatures using the EdDSA algorithm.
class ED25519Signer {
/// The hash function used for generating the message digest.
final AHash hashFunction;

/// The EdDSA private key used for signing the message.
final ED25519PrivateKey privateKey;

ED25519Signer({
required this.hashFunction,
required this.privateKey,
});

/// Generates a deterministic signature for a given message using [ED25519PrivateKey].
EDSignature sign(Uint8List message) {
Uint8List publicKey = privateKey.publicKey.bytes;
Uint8List h = hashFunction.convert(privateKey.bytes).byteList;
Uint8List prefix = h.sublist(privateKey.length);

BigInt r = BigIntUtils.decode(hashFunction.convert(<int>[...prefix, ...message]).byteList, order: Endian.little);
Uint8List R = (CurvePoints.generatorED25519 * r).toBytes();

BigInt k = BigIntUtils.decode(hashFunction.convert(<int>[...R, ...publicKey, ...message]).byteList, order: Endian.little);
k %= CurvePoints.generatorED25519.n;

BigInt s = (r + k * privateKey.edPrivateKey.a) % CurvePoints.generatorED25519.n;
return EDSignature(
r: R,
s: BigIntUtils.changeToBytes(s, length: privateKey.length, order: Endian.little),
);
}
}
68 changes: 68 additions & 0 deletions lib/src/cdsa/eddsa/ed25519/signer/ed25519_verifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Class was shaped by the influence of several key sources including:
// "blockchain_utils" Copyright (c) 2010 Mohsen
// https://github.com/mrtnetwork/blockchain_utils/.
//
// BSD 3-Clause License
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import 'dart:typed_data';

import 'package:cryptography_utils/cryptography_utils.dart';
import 'package:cryptography_utils/src/cdsa/eddsa/ed25519/signer/ed_signature.dart';
import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart';
import 'package:cryptography_utils/src/utils/big_int_utils.dart';

/// This class implements the functionality necessary to verify digital signatures using the EdDSA algorithm.
class ED25519Verifier {
/// The hash function used for generating the message digest.
final AHash hashFunction;

/// The EdDSA public key used for signing the message.
final ED25519PublicKey publicKey;

ED25519Verifier({
required this.hashFunction,
required this.publicKey,
});

/// Verifies an ED25519 signature against given message.
bool isSignatureValid(Uint8List message, EDSignature edSignature) {
EDPoint R = EDPoint.fromBytes(CurvePoints.generatorED25519, edSignature.r);
BigInt S = BigIntUtils.decode(edSignature.s, order: Endian.little);
if (S >= CurvePoints.generatorED25519.n) {
throw Exception('Invalid signature');
}

Uint8List digest = hashFunction.convert(<int>[...R.toBytes(), ...publicKey.bytes, ...message]).byteList;
BigInt k = BigIntUtils.decode(digest, order: Endian.little);
EDPoint gs = (CurvePoints.generatorED25519 * S).scaleToAffineCoordinates();
EDPoint rka = (publicKey.edPublicKey.A * k + R).scaleToAffineCoordinates();
if (gs != rka) {
return false;
}
return true;
}
}
47 changes: 47 additions & 0 deletions lib/src/cdsa/eddsa/ed25519/signer/ed_signature.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:cryptography_utils/cryptography_utils.dart';

/// Class representing a digital signature in the EdDSA algorithm
class EDSignature extends ASignature {
/// The part of the signature representing the point on the Edwards curve, typically denoted as 'R'.
/// This is a unique identifier for the signature, generated as part of the signing process.
final Uint8List r;

/// The part of the signature representing the scalar component, typically denoted as 'S'.
/// This value is computed from the signer's private key, the message's hash, and the point 'R',
/// serving as the proof of the signature's authenticity and integrity.
final Uint8List s;

/// Constructs an instance of ECSignature with the specified 'r' and 's' components.
const EDSignature({
required this.r,
required this.s,
});

/// Constructs an instance of ECSignature from a base64 string.
factory EDSignature.fromBase64(String base64) {
Uint8List bytes = base64Decode(base64);
return EDSignature.fromBytes(bytes);
}

/// Constructs an instance of ECSignature from a byte array.
factory EDSignature.fromBytes(Uint8List bytes) {
return EDSignature(
r: bytes.sublist(0, 32),
s: bytes.sublist(32, 64),
);
}

/// Returns the signature as a byte array.
@override
Uint8List get bytes => Uint8List.fromList(r + s);

/// Returns the length of the signature.
@override
int get length => r.length + s.length;

@override
List<Object?> get props => <Object?>[r, s];
}
39 changes: 39 additions & 0 deletions lib/src/cdsa/eddsa/ed_curve.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:equatable/equatable.dart';

/// [EDCurve] represents an Edwards curve used in elliptic curve cryptography (ECC).
/// Edwards curves offer several advantages over other curve types, including faster arithmetic operations
/// and strong security properties, making them suitable for a wide range of cryptographic applications.

/// In ECC, an [EDCurve] is characterized by its equation, typically of the form x^2 + y^2 = 1 + dx^2y^2 in a finite field.
/// This equation defines the mathematical structure of the Edwards curve, where 'd' is a non-square element in the field,
/// and the curve parameters are chosen to optimize security and performance.

/// The curve is used to generate public-private key pairs and to perform operations like digital signatures.
/// It operates in a finite field, meaning that the values of the points on the curve are limited to a fixed range.
class EDCurve extends Equatable {
/// A constant in the elliptic curve equation.
/// Determines the specific curve used and impacts the cryptographic problem's difficulty.
final BigInt a;

/// A constant in the edward curve equation.
/// Defines the curve's shape crucial for ECDSA cryptographic properties.
final BigInt d;

/// The cofactor of the edward curve, related to the curve's point count,
/// used in calculations for subgroup security enhancement.
final BigInt h;

/// The prime number that defines the field over which the elliptic curve is defined,
/// crucial for modulo operations in ECDSA.
final BigInt p;

const EDCurve({
required this.a,
required this.d,
required this.h,
required this.p,
});

@override
List<Object?> get props => <Object>[a, d, h, p];
}
Loading