c0mm4nd / dart-elliptic

Elliptic curves and key pair generations in dart
https://pub.dev/packages/elliptic
MIT License
6 stars 2 forks source link

Encrypt a data for a given public key using ECIES algorithm with P256 Curve #3

Closed redDwarf03 closed 3 years ago

redDwarf03 commented 3 years ago

Hello

I don't know if you see my mail. Perhaps it's better to indicate the issue in github :)

First, I would like to thank you again for your different answers for my needs about crypto in flutter. I confess I'm not able to write crypto codes and your work is impressive !

I need your help for the last time, if possible. I almost finished my job but I have one last problem to solve and i think you may be able to help me

When I execute the test code in my project with the command "flutter test" https://github.com/redDwarf03/archethic_lib_dart

I have 2 issues (One issue twice... same pb)

  package:crypto_keys/src/pointycastle_ext.dart 225:9    BlockCipherWithAuthenticationTag.process
  package:crypto_keys/src/symmetric_operator.dart 57:23  _SymmetricEncrypter.decrypt
  package:archethic_lib_dart/crypto.dart 574:41          aesAuthDecrypt
  package:archethic_lib_dart/crypto.dart 407:14          ecDecrypt
  test/crypto_test.dart 106:16                           main.<fn>.<fn>.<fn>

I don't know If I don't use correctly your lib or other one... but I think I you watch my issue, you can find quickly :)

Could you help me ?

My lib is the traduction of the JS project : https://github.com/archethic-foundation/libjs

Thank you

NB: the code if you don't dl my project

Test:

 test('should encrypt a data using a P256 public key', () {
        final KeyPair keypair = crypto.deriveKeyPair('seed', 0, curve: 'P256');
        final Uint8List cipherText =
            crypto.ecEncrypt('hello', keypair.publicKey);
        expect(crypto.ecDecrypt(cipherText, keypair.privateKey), 'hello');
      });

// Dart imports:
import 'dart:convert' show utf8;
import 'dart:math' show Random;
import 'dart:typed_data' show Uint8List;

// Package imports:
import 'package:crypto/crypto.dart' as crypto show Hmac, sha256, sha512, Digest;
import 'package:crypto_keys/crypto_keys.dart' as cryptoKeys;
import 'package:ecdsa/ecdsa.dart' as ecdsa;
import 'package:elliptic/elliptic.dart' as elliptic;
import 'package:elliptic/ecdh.dart' as ecdh;
import 'package:pinenacl/ed25519.dart' as ed25519;
import 'package:pointycastle/export.dart' show Digest;

// Project imports:
import 'package:archethic_lib_dart/model/aes_auth_encrypt_infos.dart';
import 'package:archethic_lib_dart/model/key_pair.dart';
import 'package:archethic_lib_dart/model/secret.dart';
import 'package:archethic_lib_dart/utils.dart';

/// Encrypt a data for a given public key using ECIES algorithm
/// @param {Uint8List} data Data to encrypt
/// @param {Uint8List} publicKey Public key for the shared secret encryption
Uint8List ecEncrypt(Uint8List data, Uint8List publicKey) {

  final Uint8List curveBuf = publicKey.sublist(0, 1);
  final Uint8List pubBuf = publicKey.sublist(2, publicKey.length);

  switch (curveBuf[0]) {
    case 1:
      final elliptic.EllipticCurve ec = elliptic.getP256();
      final elliptic.PrivateKey privateKey = ec.generatePrivateKey();
      final elliptic.PublicKey publicKey =
          elliptic.PublicKey.fromHex(ec, uint8ListToHex(pubBuf));
      final Uint8List sharedKey = Uint8List.fromList(ecdh.computeSecret(privateKey, publicKey));
      final Secret secret = deriveSecret(sharedKey);
      final AesAuthEncryptInfos aesAuthEncryptInfos =
          aesAuthEncrypt(data, secret.aesKey, secret.iv);
      return concatUint8List([
        hexToUint8List(publicKey.toHex()),
        aesAuthEncryptInfos.tag,
        aesAuthEncryptInfos.encrypted
      ]);
    default:
      throw 'Curve not supported';
  }
}

Secret deriveSecret(Uint8List  sharedKey) {

  crypto.Hmac hmac = crypto.Hmac(crypto.sha256, Uint8List(0));
  crypto.Digest digest = hmac.convert(sharedKey);
  final Uint8List pseudoRandomKey = Uint8List.fromList(digest.bytes);

  hmac = crypto.Hmac(crypto.sha256, pseudoRandomKey);
  digest = hmac.convert(utf8.encode('0'));
  final Uint8List iv = Uint8List.fromList(digest.bytes.sublist(0, 32));

  hmac = crypto.Hmac(crypto.sha256, iv);
  digest = hmac.convert(utf8.encode('1'));
  final Uint8List aesKey = Uint8List.fromList(digest.bytes.sublist(0, 32));

  return Secret(iv: iv, aesKey: aesKey);
}

AesAuthEncryptInfos aesAuthEncrypt(
    Uint8List data, Uint8List aesKey, Uint8List iv) {
  final cryptoKeys.KeyPair keyPair = cryptoKeys.KeyPair.symmetric(
      cryptoKeys.SymmetricKey(keyValue: aesKey));

  final cryptoKeys.Encrypter encrypter = keyPair.publicKey!
      .createEncrypter(cryptoKeys.algorithms.encryption.aes.gcm);

  final cryptoKeys.EncryptionResult v =
      encrypter.encrypt(data, initializationVector: iv);

  return new AesAuthEncryptInfos(tag: v.authenticationTag!, encrypted: v.data);
}

Uint8List aesAuthDecrypt(
    Uint8List encrypted, Uint8List aesKey, Uint8List iv, Uint8List tag) {
  final cryptoKeys.KeyPair keyPair = cryptoKeys.KeyPair.symmetric(
      cryptoKeys.SymmetricKey(keyValue: aesKey));

  final cryptoKeys.Encrypter decrypter = keyPair.privateKey!
      .createEncrypter(cryptoKeys.algorithms.encryption.aes.gcm);

  final Uint8List decrypted = decrypter.decrypt(cryptoKeys.EncryptionResult(
      encrypted,
      initializationVector: iv,
      authenticationTag: tag));

  return decrypted;
}
c0mm4nd commented 3 years ago

Sorry these days I was busy with debuging packages and implementing the schnorr signature.

I see you use the Publickey.fromHex in https://github.com/redDwarf03/archethic_lib_dart/blob/4d8208e21ba6ce8cf205c48756f17ba87fdef972/lib/crypto.dart#L379 which contains bug on parsing the compressed hex before v0.3.4 (uploaded yesterday). Could you please test this again with the v0.3.4 version?

If the problem still exists, please directly provide the input params and output result of this package's functions, which will be helpful on quickly reproducing.

redDwarf03 commented 3 years ago

no pb I tested with 0.3.4 but same issue

ecEncrypt: pubBuf: [4, 77, 145, 160, 161, 167, 207, 6, 162, 144, 45, 56, 66, 248, 45, 39, 145, 188, 191, 62, 230, 246, 220, 141, 224, 249, 14, 83, 233, 153, 28, 60, 179, 54, 132, 183, 185, 230, 111, 38, 231, 201, 245, 48, 47, 115, 198, 152, 151, 190, 95, 48, 29, 233, 166, 53, 33, 160, 138, 196, 239, 52, 193, 135, 40]
ecEncrypt: sharedKey: [237, 148, 203, 8, 141, 46, 132, 177, 250, 212, 177, 89, 206, 36, 123, 176, 46, 59, 165, 215, 24, 231, 150, 87, 123, 29, 209, 97, 234, 205, 96, 154]
ecEncrypt: data: [104, 101, 108, 108, 111]
ecEncrypt: secret.aesKey: [196, 84, 123, 122, 140, 219, 170, 39, 105, 73, 71, 107, 21, 42, 177, 201, 32, 124, 119, 83, 207, 28, 128, 213, 139, 146, 153, 80, 134, 28, 108, 149]
ecEncrypt: secret.iv: [28, 87, 98, 173, 37, 204, 47, 226, 62, 231, 131, 209, 182, 158, 99, 20, 72, 84, 163, 203, 5, 253, 147, 78, 187, 239, 10, 197, 36, 190, 18, 64]
ecEncrypt: publicKey.toHex(): 044d91a0a1a7cf06a2902d3842f82d2791bcbf3ee6f6dc8de0f90e53e9991c3cb33684b7b9e66f26e7c9f5302f73c69897be5f301de9a63521a08ac4ef34c18728
ecEncrypt: privateKey.toHex(): ad09b0c32e859c801d1248fb3a9ec9819886d9e887f3411b7ba3f8e9acc688b2
ecEncrypt: aesAuthEncryptInfos.tag: [165, 148, 210, 125, 179, 158, 222, 50, 104, 49, 250, 91, 205, 106, 116, 252]
ecEncrypt: aesAuthEncryptInfos.encrypted: [58, 138, 117, 36, 133]

ecDecrypt: cipherText: [4, 77, 145, 160, 161, 167, 207, 6, 162, 144, 45, 56, 66, 248, 45, 39, 145, 188, 191, 62, 230, 246, 220, 141, 224, 249, 14, 83, 233, 153, 28, 60, 179, 54, 132, 183, 185, 230, 111, 38, 231, 201, 245, 48, 47, 115, 198, 152, 151, 190, 95, 48, 29, 233, 166, 53, 33, 160, 138, 196, 239, 52, 193, 135, 40, 165, 148, 210, 125, 179, 158, 222, 50, 104, 49, 250, 91, 205, 106, 116, 252, 58, 138, 117, 36, 133]
ecDecrypt: pvBuf: [195, 229, 236, 145, 55, 160, 195, 144, 162, 29, 197, 149, 140, 218, 218, 5, 157, 10, 157, 95, 39, 243, 154, 127, 66, 116, 119, 118, 200, 5, 71, 239]
ecDecrypt: ephemeralPubKey: [4, 77, 145, 160, 161, 167, 207, 6, 162, 144, 45, 56, 66, 248, 45, 39, 145, 188, 191, 62, 230, 246, 220, 141, 224, 249, 14, 83, 233, 153, 28, 60, 179, 54, 132, 183, 185, 230, 111, 38, 231, 201, 245, 48, 47, 115, 198, 152, 151, 190, 95, 48, 29, 233, 166, 53, 33, 160, 138, 196, 239, 52, 193, 135, 40]
ecDecrypt: tag: [165, 148, 210, 125, 179, 158, 222, 50, 104, 49, 250, 91, 205, 106, 116, 252]
ecDecrypt: encrypted: [58, 138, 117, 36, 133]
ecDecrypt: privateKey.toHex(): c3e5ec9137a0c390a21dc5958cdada059d0a9d5f27f39a7f42747776c80547ef
ecDecrypt: publicKey.toHex(): 044d91a0a1a7cf06a2902d3842f82d2791bcbf3ee6f6dc8de0f90e53e9991c3cb33684b7b9e66f26e7c9f5302f73c69897be5f301de9a63521a08ac4ef34c18728
ecDecrypt: sharedKey: [90, 65, 231, 130, 57, 8, 233, 62, 238, 173, 146, 54, 98, 82, 218, 127, 143, 105, 230, 226, 195, 210, 232, 210, 55, 137, 89, 130, 167, 215, 176, 123]
ecDecrypt: secret.aesKey: [121, 94, 31, 40, 243, 222, 102, 130, 160, 63, 169, 77, 32, 100, 9, 30, 51, 181, 105, 143, 112, 84, 112, 165, 106, 249, 74, 75, 132, 222, 19, 75]
ecDecrypt: secret.iv: [52, 0, 157, 157, 151, 61, 236, 135, 122, 72, 150, 118, 85, 58, 76, 236, 100, 28, 57, 87, 11, 60, 247, 254, 79, 67, 3, 120, 2, 225, 31, 111]

Auth error
BlockCipherWithAuthenticationTag.process
package:crypto_keys/src/pointycastle_ext.dart:225
_SymmetricEncrypter.decrypt
package:crypto_keys/src/symmetric_operator.dart:57
aesAuthDecrypt
package:archethic_lib_dart/crypto.dart:598
ecDecrypt
package:archethic_lib_dart/crypto.dart:414
main.<fn>.<fn>.<fn>
test\crypto_test.dart:99
c0mm4nd commented 3 years ago

Problem 1.

Uint8List ecEncrypt(data, publicKey) {
      ...
      return concatUint8List([
        hexToUint8List(publicKey.toHex()),
        aesAuthEncryptInfos.tag,
        aesAuthEncryptInfos.encrypted
      ]);

hexToUint8List(publicKey.toHex()), should be hexToUint8List(privateKey.publicKey.toHex()), (use ecdh's host key)

c0mm4nd commented 3 years ago

Problem 2.

comparing bytes with the str

expect(crypto.ecDecrypt(cipherText, keypair.privateKey), 'hello');

The 'hello' should be 'hello'.codeUnits

c0mm4nd commented 3 years ago

image

Pass the test

redDwarf03 commented 3 years ago

yeah!!!! thank you so much ! now, I have to finish with X25519 but it's not your problem nor your library ;)

c0mm4nd commented 3 years ago

Curve25519 integration task (into this elliptic curve lib) will get started after finishing schnorr signature

redDwarf03 commented 3 years ago

i will be attentive... I search for library without dependencies with PointyCastle. Do you know when you will finish Schnorr Signature ?