Closed azim92 closed 3 years ago
@azim92 As far as i remember, the ECDSA Signing was not yet available when implementing the CryptoUtils. I will take a look on the current stage of the Pointycastle project and check if this is still true or not.
@Ephenodrom
Thank you for your response. If you don't mind, could you have a look at my ECDSA verify/signer with SHA256? I'm not a knowledgeable individual for crypto related, so would like to inquire for ECDSA signer, which one is the standardize for generating an ECDSA signature? A Probabilistic Signature (Non-Static Signature) or Deterministic Signature (Static Signature)?
Static here indicates the same signature output per signature generation.
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:basic_utils/basic_utils.dart';
import 'package:pointycastle/api.dart';
import 'package:pointycastle/asn1.dart';
import 'package:pointycastle/ecc/api.dart';
import 'package:pointycastle/export.dart';
import 'package:pointycastle/src/utils.dart' as pcUtils;
import 'package:asn1lib/asn1lib.dart' as asnLib;
static Uint8List ecSign(ECPrivateKey privateKey, Uint8List plainDataByte) {
var signer = Signer('SHA-256/ECDSA');
var privateParams = PrivateKeyParameter<ECPrivateKey>(privateKey);
// probabilistic signature
var secureRandom = FortunaRandom();
var random = Random.secure();
var seeds = List<int>.generate(32, (_) => random.nextInt(255));
secureRandom.seed(KeyParameter(Uint8List.fromList(seeds)));
var signatureParams = ParametersWithRandom(privateParams, secureRandom);
signer.init(true, signatureParams);
// deterministic signature
// var signer = ECDSASigner(SHA256Digest(), HMac(SHA256Digest(), 64));
// signer.init(true, PrivateKeyParameter<ECPrivateKey>(privateKey));
return ecdsaSignatureToASN1Byte(signer.generateSignature(plainDataByte));
}
static bool ecVerify(
ECPublicKey publicKey, Uint8List plainDataByte, Uint8List signature) {
final verifier = ECDSASigner(SHA256Digest(), HMac(SHA256Digest(), 64));
verifier.init(false, PublicKeyParameter<ECPublicKey>(publicKey));
return verifier.verifySignature(
plainDataByte, ecdsaSignatureFromASN1Byte(signature));
}
static Uint8List ecdsaSignatureToASN1Byte(ECSignature signature) {
var algorithmSeq = new asnLib.ASN1Sequence();
var r = new asnLib.ASN1Integer(signature.r);
var s = new asnLib.ASN1Integer(signature.s);
algorithmSeq.add(r);
algorithmSeq.add(s);
return algorithmSeq.encodedBytes;
}
static ECSignature ecdsaSignatureFromASN1Byte(Uint8List signatureByte) {
var parser = ASN1Parser(signatureByte);
var object = parser.nextObject() as ASN1Sequence;
var r = pcUtils.decodeBigInt(object.elements.elementAt(0).valueBytes);
var s = pcUtils.decodeBigInt(object.elements.elementAt(1).valueBytes);
return ECSignature(r, s);
}
for ecdsaSignatureToASN1Byte(...)
function, I had to use ASN1 from asn1lib: ^0.8.1
package as
the one provided in pointycastle: ^2.0.1
gives me an empty ASN1Sequence after adding ASN1Integer to it:
var algorithmSeq = new asnLib.ASN1Sequence();
var r = new asnLib.ASN1Integer(signature.r);
var s = new asnLib.ASN1Integer(signature.s);
algorithmSeq.add(r);
algorithmSeq.add(s);
@azim92 Please upgrade to version 3.0.0 and you will find two new methods for EC Sign and EC Verify. Please try it out and give some feedback.
PS: The documented list of supported algorithm is not complete, I will have to check again which algorithm are supported and update the list with the next release.
Using basic_utils: ^3.0.0-nullsafety.0
My Test Cases:
import 'dart:typed_data';
import 'package:basic_utils/basic_utils.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pointycastle/ecc/api.dart';
void main() {
var keyPair = CryptoUtils.generateEcKeyPair();
Uint8List signDataByte = Uint8List.fromList('Hello'.codeUnits);
test('TEST SHA-1/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-1/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-1/ECDSA'), true);
});
test('TEST SHA-3/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-3/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-3/ECDSA'), true);
});
test('TEST SHA-224/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-224/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-224/ECDSA'), true);
});
test('TEST SHA-256/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-256/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-256/ECDSA'), true);
});
test('TEST SHA-384/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-384/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-384/ECDSA'), true);
});
test('TEST SHA-512/ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-512/ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-512/ECDSA'), true);
});
test('TEST SHA-1/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-1/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-1/DET-ECDSA'), true);
});
test('TEST SHA-3/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-3/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-3/DET-ECDSA'), true);
});
test('TEST SHA-224/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-224/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-224/DET-ECDSA'), true);
});
test('TEST SHA-256/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-256/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-256/DET-ECDSA'), true);
});
test('TEST SHA-384/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-384/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-384/DET-ECDSA'), true);
});
test('TEST SHA-512/DET-ECDSA Algorithm', (){
var sig = CryptoUtils.ecSign(keyPair.privateKey as ECPrivateKey, signDataByte, algorithmName: 'SHA-512/DET-ECDSA');
expect(CryptoUtils.ecVerify(keyPair.publicKey as ECPublicKey, signDataByte, sig, algorithm: 'SHA-512/DET-ECDSA'), true);
});
}
Results:
Not too sure what happened with SHA-3/ECDSA and SHA-3/DET-ECDSA.
Your EC Sign will support only probabilistic signature I assume?
This seems to be more a problem of "Pointycastle". It seems the package does not support SHA-3/ECDSA and SHA-3/DET-ECDSA.
I would recommend to open an issue here : https://github.com/bcgit/pc-dart
Then this is possible I just have to update the pointycastle version.
The code documentation has now all working algorithm documented.
Hi, was testing out your library since one of it's dependency is PointyCastle. Just would like to know if there is an ECDSA Sign/Verifier included in your CryptoUtils, or in another dart file?