Giter Club home page Giter Club logo

crypto_keys's Introduction

Build Status ❤️ sponsor

A library for doing cryptographic signing/verifying and encrypting/decrypting.

It uses pointycastle under the hood, but exposes a more convenient api.

Usage

Signing

A simple usage example:

import 'package:crypto_keys/crypto_keys.dart';
import 'dart:typed_data';

main() {
  // Create a key pair from a JWK representation
  var keyPair = new KeyPair.fromJwk({
    "kty": "oct",
    "k": "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75"
        "aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"
  });

  // A key pair has a private and public key, possibly one of them is null, if
  // required info was not available when construction
  // The private key can be used for signing
  var privateKey = keyPair.privateKey;

  // Create a signer for the key using the HMAC/SHA-256 algorithm
  var signer = privateKey.createSigner(algorithms.signing.hmac.sha256);

  // Sign some content, to be integrity protected
  var content = "It's me, really me";
  var signature = signer.sign("It's me, really me".codeUnits);

  print("Signing '$content'");
  print("Signature: ${signature.data}");

  // The public key can be used for verifying the signature
  var publicKey = keyPair.publicKey;

  // Create a verifier for the key using the specified algorithm
  var verifier = publicKey.createVerifier(algorithms.signing.hmac.sha256);

  var verified =
      verifier.verify(new Uint8List.fromList(content.codeUnits), signature);
  if (verified)
    print("Verification succeeded");
  else
    print("Verification failed");
}

Encryption

A simple usage example:

import 'package:crypto_keys/crypto_keys.dart';
import 'dart:typed_data';

main() {
  // Generate a new random symmetric key pair
  var keyPair = new KeyPair.generateSymmetric(128);

  // Use the public key to create an encrypter with the AES/GCM algorithm
  var encrypter =
      keyPair.publicKey.createEncrypter(algorithms.encryption.aes.gcm);

  // Encrypt the content with an additional authentication data for integrity
  // protection
  var content = "A very secret text";
  var aad = "It is me";
  var v = encrypter.encrypt(new Uint8List.fromList(content.codeUnits),
      additionalAuthenticatedData: new Uint8List.fromList(aad.codeUnits));

  print("Encrypting '$content'");
  print("Ciphertext: ${v.data}");
  print("Authentication tag: ${v.authenticationTag}");

  // Use the private key to create the decrypter
  var decrypter =
      keyPair.privateKey.createEncrypter(algorithms.encryption.aes.gcm);

  // Decrypt and verify authentication tag
  var decrypted = decrypter.decrypt(v);

  print("Decrypted text: '${new String.fromCharCodes(decrypted)}'");
}

Features and bugs

Please file feature requests and bugs at the issue tracker.

Sponsor

Creating and maintaining this package takes a lot of time. If you like the result, please consider to ❤️ sponsor. With your support, I will be able to further improve and support this project. Also, check out my other dart packages at pub.dev.

crypto_keys's People

Contributors

acoutts avatar jpeiffer avatar muhammadsaddamnur avatar rbellens avatar tallinn1960 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

crypto_keys's Issues

Data signed with an elliptic curve private key is not always valid

I am generating an EC Keypair using 'curve/P-256' and signing with 'sig/ECDSA/SHA-256'. I'm signing 196 bytes of data (a Webauthn payload). When I use openssl to verify the signature on the data, it's failing a fair amount of the time. Sometimes using the same keypair some signatures fail and others succeed. I have noticed that using the same keys openssl generates signatures that are always 1 byte longer. I don't know if that matters or not.

I have a script that I've been using to test this. It uses a couple of packages beside this one for encoding the keys to PEM data for use with openssl. It can be found here: https://gist.github.com/killermonk/92644b4fb25140cb02be17a9ffb45b26

For instance, the following keypair produced 3 invalid signatures and 1 valid signature for the specified data according to openssl. Using the crypto_keys library, all of these signatures verify correctly.

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILmQQdr5RTLdaVb0y1/YmEEpr+/BiEDauY+RxF8J0D2eoAoGCCqGSM49
AwEHoUQDQgAEuWNCjiuJI6wjmXiAWQARxcJIwI5UIli+JjDp0jvbzvEq4hz39Bal
m9Nzb8UHCXALkXPlE/INUdZHCEetjb1N+A==
-----END EC PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuWNCjiuJI6wjmXiAWQARxcJIwI5U
Ili+JjDp0jvbzvEq4hz39Balm9Nzb8UHCXALkXPlE/INUdZHCEetjb1N+A==
-----END PUBLIC KEY-----

Data:

SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2NFAAAAAAAAAAAAAAAAAAAA
AAAAAAAAIJ8GmAMTvViqN5KZbdSxTZv20+ju7xYtpV+6qTEXhvexpQECAyYgASFY
ICPerAPyLHdkODGoX9CLNOhU9ypFkuzQpBmcfjGzh59yIlggyBY1OeDgVzouqvNm
Ixhk+PWtHpfJGMs7KUO8XeT24546zU3Said3e9M41W5Tc3+uWEyaI1HSve9jSHGZ
I9S8bw==

Valid signature:

MEQCICK34CYPN08BAF6lygmYNxPlsT1wJCe462NTvfhZ2Y+UAiAyZoq8ajsu3EDd
Us5w+0STCr0nPiOmBM/I0H+BAAE2Qg==

Invalid signatures:

MEQCIOLaRaTS4NtaAJJPYcuGUe5AsDCuEe5fWvCFWq/b0YRNAiDoOA0oEUtYqPRf
o7XVhvkOjioNbbBB5gSBjas9GZUGVg==

MEQCIK5aZSxsurxLwMCYtiXj+9FW+Z6zvHUDxFs52z7fwSJHAiDmcDTH5zzDuBJ5
M5xyctOIXaUPAcrcP+69mBr/qnyA4w==

MEQCINxMx+FHIRl+BH9l0rEwGnuDg80Zm4MgkhDqOUF425jbAiCQ1ONq9Wq85BXh
mZg22hBqXDsj1zIyk1uNrBRPoeGxLQ==

OpenSSL signature using the same keys:

MEUCICbcTkpUk8N9OBvfCpxhCOFCy5Trj3Nzog1PsnDvA/QCAiEAmi9P/VkuY6xx
WD8KFx35mU/7XHf6P6A57CX9CXTvX4Q=

Auth error

Bug found. Sorry for the inconvenience.

pointycastle update

Hello,

There is a bug in pointycastle 3.0.0, which has been solved in 3.2.0
Could this package be updated to 3.2.0, so I don't need to manually override pointycastle: ^3.2.0?

Thanks

RSAES OAEP support

Hi,

First of all: thanks a lot for this library! I'm trying to implement OpenID connect with Itsme (Belgian mobile id) through it (and the jose plugin)

Is there a reason RSAES OAEP is not implemented?

It seems that if I change the code (algorithms.dart, line 92) from
final oaep = new AlgorithmIdentifier._( "enc/RSA/ECB/OAEPWithSHA-1AndMGF1Padding", () => throw new UnimplementedError("RSA OAEP mode not implemented"));
to
final oaep = new AlgorithmIdentifier._( "enc/RSA/ECB/OAEPWithSHA-1AndMGF1Padding", () => new pc.OAEPEncoding(new pc.RSAEngine()));
it will work.
Itsme seems to be using this for JWT - JWS - JWE encryption.

kind regards,

Jeroen

Unable to use `ES256K` algorithm

I was trying to implement JOSE/JWT using ES256K algorithm using (jose)[https://pub.dev/packages/jose], which listed as supported signing algo JWS on it's README. But, turns out it did not work and give me error that algo is not supported. I tried to dig out on the source code and found that the algo is not listed on the library and also in this library that listed as it's dependency.

I've created this (PR) that works for me right now, Please kindly review!

Thank you!

ECIES Support

Hello
good job for your library! Thx
Do you know when you will complete the encryption ECIES with AEAD and HKDF

i would like to try to implement in dart this js code

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

        if (typeof(data) !== "string" && !data instanceof Uint8Array) {
            throw "'data' must be a string or Uint8Array"
        }

        if (typeof(publicKey) !== "string" && !publicKey instanceof Uint8Array) {
            throw "'publicKey' must be a string or Uint8Array"
        }

        if (typeof(data) == "string") {
            if(isHex(data)) {
                data = hexToUint8Array(data)
            } else {
                data = new TextEncoder().encode(data)
            }
        }

        if (typeof(publicKey) == "string") {
            if(isHex(publicKey)) {
                publicKey = hexToUint8Array(publicKey)
            } else {
                throw "'publicKey' must be an hexadecimal string"
            }
        }

        curve_buf = publicKey.slice(0, 1)
        pubBuf = publicKey.slice(2, publicKey.length)


        switch (curve_buf[0]) {
           case 0:
             const { public: ephemeralPublicKey, private: ephemeralPrivateKey} = curve25519.generateKeyPair(randomBytes(32))  
             const curve25519pub = ed2curve.convertPublicKey(pubBuf)

             var sharedKey = curve25519.sharedKey(ephemeralPrivateKey, curve25519pub)
             var { aesKey, iv } = deriveSecret(sharedKey)
             
             var { tag, encrypted } = aesAuthEncrypt(data, aesKey, iv)
            
            return concatUint8Arrays([
               Uint8Array.from(ephemeralPublicKey),
               tag,
               encrypted
             ])
          case 1: 
            ecdh = createECDH("prime256v1")
            ecdh.generateKeys(); 
            sharedKey = ecdh.computeSecret(pubBuf)
            
            var { aesKey, iv } = deriveSecret(sharedKey)
            var { tag, encrypted} = aesAuthEncrypt(data, aesKey, iv)

            return concatUint8Arrays([
              Uint8Array.from(ecdh.getPublicKey()),
              tag,
              encrypted
            ])
          case 2: 
            ecdh = createECDH("secp256k1")
            ecdh.generateKeys(); 
            sharedKey = ecdh.computeSecret(pubBuf)

            var { aesKey, iv } = deriveSecret(sharedKey)

            var { tag, encrypted} = aesAuthEncrypt(data, aesKey, iv)

            return concatUint8Arrays([
              Uint8Array.from(ecdh.getPublicKey()),
              tag,
              encrypted
            ])
          
          default:
            throw "Curve not supported"
        }
    },

Migrate to null safety

This package will need to be migrated to null safety as soon as all of it upstream packages have nullsafety releases available.

If decrypt with individual authenticate param, It will be more readable.

// encode have authenticate
var v = encrypter.encrypt(new Uint8List.fromList(content.codeUnits),
additionalAuthenticatedData: new Uint8List.fromList(aad.codeUnits));
...
// decode authencate was the child of v, lead a problem, if I need send a encrypt data through network, how can I protect the encrypt data, and ensure, the receiver can decode it easily?
var decrypted = decrypter.decrypt(v)

GCM - Web compatibility

Hello

First, thx for your lib !

I have an error with Uint64List in flutter Web (in pointycastle lib)

var length = Uint8List.view((Uint64List(2)..[0] = iv.length * 8).buffer);

""Error: Unsupported operation: Uint64List not supported on the web.
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49  throw_
dart-sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart 115:5       new
packages/pointycastle/block/modes/gcm.dart 81:36                              [_computeInitialCounter]
packages/pointycastle/block/modes/gcm.dart 61:16                              prepare
packages/pointycastle/src/impl/base_aead_block_cipher.dart 217:5              reset
packages/pointycastle/block/modes/gcm.dart 47:11                              reset
packages/pointycastle/src/impl/base_aead_block_cipher.dart 117:5              init
packages/pointycastle/block/modes/gcm.dart 40:11                              init
packages/crypto_keys/src/symmetric_operator.dart 71:16                        encrypt
packages/archethic_lib_dart/src/utils/crypto.dart 673:16                      aesAuthEncrypt
packages/archethic_lib_dart/src/utils/crypto.dart 400:11                      ecEncrypt
packages/archethic_lib_dart/src/services/api_service.dart 483:46              newKeychainTransaction
packages/aewallet/util/keychain_util.dart 98:54                               createKeyChain
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 84:54            runBody
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 123:5            _async
packages/aewallet/util/keychain_util.dart 70:30                               createKeyChain
packages/aewallet/ui/views/intro/intro_backup_confirm.dart 547:28             createKeychain
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50            <fn>
dart-sdk/lib/async/zone.dart 1653:54                                          runUnary
dart-sdk/lib/async/future_impl.dart 147:18                                    handleValue
dart-sdk/lib/async/future_impl.dart 766:44                                    handleValueCallback
dart-sdk/lib/async/future_impl.dart 795:13                                    _propagateToListeners
dart-sdk/lib/async/future_impl.dart 566:5                                     [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 639:7                                     callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                              _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                               _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15           <fn>
"

I created an issue in pointycastle but this issue was closed directly without analyze :/
bcgit/pc-dart#178

Is it possible to change the call of symmetric_operator please ?

Thx

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.