Skip to content

Commit

Permalink
Merge pull request #494 from atsign-foundation/pass_optional_key_params
Browse files Browse the repository at this point in the history
feat: at_chops - add optional public key/private key to asymmetric encryption, major version release
  • Loading branch information
murali-shris authored Jan 24, 2024
2 parents dc4619b + 1d7c99e commit c0ea723
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 329 deletions.
6 changes: 6 additions & 0 deletions packages/at_chops/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 2.0.0
- [Breaking Change] fix: removed deprecated methods and members
- [Breaking Change] feat: Introduced interface for ASymmetricEncryptionAlgorithm and modified DefaultEncryptionAlgorithm
- build[deps]:
- changed minimum dart version in pubspec from 2.15.1 to 3.0.0
- upgraded pointycastle to 3.7.4
## 1.0.7
- build[deps]: Upgraded the following packages:
- at_commons to v4.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'external_signer.dart';

class AtChopsSecureElement extends AtChopsImpl {
late ExternalSigner externalSigner;
AtChopsSecureElement(AtChopsKeys atChopsKeys) : super(atChopsKeys);
AtChopsSecureElement(super.atChopsKeys);

@override
AtSigningResult sign(AtSigningInput signingInput) {
Expand All @@ -28,6 +28,7 @@ class AtChopsSecureElement extends AtChopsImpl {

Uint8List _getBytes(dynamic data) {
if (data is String) {
// ignore: unnecessary_cast
return utf8.encode(data) as Uint8List;
} else if (data is Uint8List) {
return data;
Expand Down
4 changes: 3 additions & 1 deletion packages/at_chops/lib/at_chops.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ export 'src/util/at_chops_util.dart';
export 'src/algorithm/algo_type.dart';
export 'src/algorithm/at_iv.dart';
export 'src/algorithm/aes_encryption_algo.dart';
export 'src/algorithm/default_encryption_algo.dart';
export 'src/algorithm/rsa_encryption_algo.dart';
export 'src/algorithm/default_signing_algo.dart';
export 'src/algorithm/pkam_signing_algo.dart';
export 'src/algorithm/ecc_signing_algo.dart';
export 'src/key/at_key_pair.dart';
export 'src/key/at_public_key.dart';
export 'src/key/at_private_key.dart';
14 changes: 14 additions & 0 deletions packages/at_chops/lib/src/algorithm/at_algorithm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ abstract class SymmetricEncryptionAlgorithm extends AtEncryptionAlgorithm {
Uint8List decrypt(Uint8List encryptedData, {InitialisationVector iv});
}

/// Interface for asymmetric encryption algorithms. Check [DefaultEncryptionAlgo] for sample implementation.
abstract class ASymmetricEncryptionAlgorithm extends AtEncryptionAlgorithm {
AtPublicKey? atPublicKey;
AtPrivateKey? atPrivateKey;

/// Encrypt [plainData] with [atPublicKey.publicKey]
@override
Uint8List encrypt(Uint8List plainData);

/// Decrypt [encryptedData] with [atPrivateKey.privateKey]
@override
Uint8List decrypt(Uint8List encryptedData);
}

/// Interface for data signing. Data is signed using private key from a key pair
/// Signed data signature is verified with public key of the key pair.
abstract class AtSigningAlgorithm {
Expand Down
32 changes: 0 additions & 32 deletions packages/at_chops/lib/src/algorithm/default_encryption_algo.dart

This file was deleted.

45 changes: 45 additions & 0 deletions packages/at_chops/lib/src/algorithm/rsa_encryption_algo.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'dart:typed_data';

import 'package:at_chops/src/algorithm/at_algorithm.dart';
import 'package:at_chops/src/key/at_private_key.dart';
import 'package:at_chops/src/key/at_public_key.dart';
import 'package:at_chops/src/key/impl/at_encryption_key_pair.dart';
import 'package:at_commons/at_commons.dart';
import 'package:crypton/crypton.dart';

class RsaEncryptionAlgo implements ASymmetricEncryptionAlgorithm {
AtEncryptionKeyPair? _encryptionKeypair;
RsaEncryptionAlgo.fromKeyPair(this._encryptionKeypair);
RsaEncryptionAlgo();
@override
Uint8List encrypt(Uint8List plainData) {
if ((_encryptionKeypair == null ||
_encryptionKeypair!.atPublicKey.publicKey.isEmpty) &&
(atPublicKey == null || atPublicKey!.publicKey.isEmpty)) {
throw AtEncryptionException('EncryptionKeypair/public key not set');
}
var publicKeyString = atPublicKey?.publicKey;
publicKeyString ??= _encryptionKeypair!.atPublicKey.publicKey;
final rsaPublicKey = RSAPublicKey.fromString(publicKeyString);
return rsaPublicKey.encryptData(plainData);
}

@override
Uint8List decrypt(Uint8List encryptedData) {
if ((_encryptionKeypair == null ||
_encryptionKeypair!.atPrivateKey.privateKey.isEmpty) &&
(atPrivateKey == null || atPrivateKey!.privateKey.isEmpty)) {
throw AtDecryptionException('EncryptionKeypair/public key not set');
}
var privateKeyString = atPrivateKey?.privateKey;
privateKeyString ??= _encryptionKeypair!.atPrivateKey.privateKey;
final rsaPrivateKey = RSAPrivateKey.fromString(privateKeyString);
return rsaPrivateKey.decryptData(encryptedData);
}

@override
AtPrivateKey? atPrivateKey;

@override
AtPublicKey? atPublicKey;
}
48 changes: 5 additions & 43 deletions packages/at_chops/lib/src/at_chops_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import 'dart:typed_data';

import 'package:at_chops/src/algorithm/at_algorithm.dart';
import 'package:at_chops/src/algorithm/at_iv.dart';
import 'package:at_chops/src/algorithm/default_encryption_algo.dart';
import 'package:at_chops/src/algorithm/rsa_encryption_algo.dart';
import 'package:at_chops/src/algorithm/default_hashing_algo.dart';
import 'package:at_chops/src/algorithm/default_signing_algo.dart';
import 'package:at_chops/src/algorithm/pkam_signing_algo.dart';
import 'package:at_chops/src/key/impl/at_chops_keys.dart';
import 'package:at_chops/src/key/key_type.dart';
import 'package:at_chops/src/metadata/at_signing_input.dart';
Expand All @@ -22,7 +20,7 @@ abstract class AtChops {
AtChops(this._atChopsKeys);

/// Encrypts the input bytes [data] using an [encryptionAlgorithm] and returns [AtEncryptionResult].
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [DefaultEncryptionAlgo]
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [RsaEncryptionAlgo]
/// [keyName] specifies which key pair to use if user has multiple key pairs configured.
/// If [keyName] is not passed default encryption/decryption keypair from .atKeys file will be used.
AtEncryptionResult encryptBytes(
Expand All @@ -32,7 +30,7 @@ abstract class AtChops {
InitialisationVector? iv});

/// Encrypts the input string [data] using an [encryptionAlgorithm] and returns [AtEncryptionResult].
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [DefaultEncryptionAlgo]
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [RsaEncryptionAlgo]
/// [keyName] specifies which key pair to use if user has multiple key pairs configured.
/// If [keyName] is not passed default encryption/decryption keypair from .atKeys file will be used.
AtEncryptionResult encryptString(
Expand All @@ -42,7 +40,7 @@ abstract class AtChops {
InitialisationVector? iv});

/// Decrypts the input bytes [data] using an [encryptionAlgorithm] and returns [AtEncryptionResult].
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [DefaultEncryptionAlgo]
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [RsaEncryptionAlgo]
/// [keyName] specifies which key pair to use if user has multiple key pairs configured.
/// If [keyName] is not passed default encryption/decryption keypair from .atKeys file will be used.
AtEncryptionResult decryptBytes(
Expand All @@ -52,7 +50,7 @@ abstract class AtChops {
InitialisationVector? iv});

/// Decrypts the input string [data] using an [encryptionAlgorithm] and returns [AtEncryptionResult].
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [DefaultEncryptionAlgo]
/// If [encryptionKeyType] is [EncryptionKeyType.rsa2048] then [encryptionAlgorithm] will be set to [RsaEncryptionAlgo]
/// [keyName] specifies which key pair to use if user has multiple key pairs configured.
/// If [keyName] is not passed default encryption/decryption keypair from .atKeys file will be used.
AtEncryptionResult decryptString(
Expand All @@ -61,42 +59,6 @@ abstract class AtChops {
String? keyName,
InitialisationVector? iv});

/// Sign the input bytes [data] using a [signingAlgorithm].
// ignore: deprecated_member_use_from_same_package
/// If [signingKeyType] is [SigningKeyType.pkamSha256] then [signingAlgorithm] will be set to [PkamSigningAlgo]
// ignore: deprecated_member_use_from_same_package
/// If [signingKeyType] is [SigningKeyType.signingSha256] then [signingAlgorithm] will be set to [DefaultSigningAlgo]
// ignore: deprecated_member_use_from_same_package
AtSigningResult signBytes(Uint8List data, SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm});

/// Verify the [signature] of bytes [data] using a [signingAlgorithm]
// ignore: deprecated_member_use_from_same_package
/// If [signingKeyType] is [SigningKeyType.pkamSha256] then [signingAlgorithm] will be set to [PkamSigningAlgo]
// ignore: deprecated_member_use_from_same_package
/// If [signingKeyType] is [SigningKeyType.signingSha256] then [signingAlgorithm] will be set to [DefaultSigningAlgo]
AtSigningResult verifySignatureBytes(
Uint8List data,
Uint8List signature,
// ignore: deprecated_member_use_from_same_package
SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm});

/// Sign the input string [data] using a [signingAlgorithm].
/// If [signingKeyType] is [SigningKeyType.pkamSha256] then [signingAlgorithm] will be set to [PkamSigningAlgo]
/// If [signingKeyType] is [SigningKeyType.signingSha256] then [signingAlgorithm] will be set to [DefaultSigningAlgo]
@Deprecated('Use sign() instead')
AtSigningResult signString(String data, SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm});

/// Verify the [signature] of string [data] using a [signingAlgorithm]
/// If [signingKeyType] is [SigningKeyType.pkamSha256] then [signingAlgorithm] will be set to [PkamSigningAlgo]
/// If [signingKeyType] is [SigningKeyType.signingSha256] then [signingAlgorithm] will be set to [DefaultSigningAlgo]
@Deprecated('Use verify() instead')
AtSigningResult verifySignatureString(
String data, String signature, SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm});

/// Compute data signature using the private key from a key pair
/// Input has to be set using [AtSigningInput] object
/// Please refer to [AtSigningInput] to create a valid input instance
Expand Down
104 changes: 7 additions & 97 deletions packages/at_chops/lib/src/at_chops_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import 'package:at_chops/src/algorithm/aes_encryption_algo.dart';
import 'package:at_chops/src/algorithm/algo_type.dart';
import 'package:at_chops/src/algorithm/at_algorithm.dart';
import 'package:at_chops/src/algorithm/at_iv.dart';
import 'package:at_chops/src/algorithm/default_encryption_algo.dart';
import 'package:at_chops/src/algorithm/rsa_encryption_algo.dart';
import 'package:at_chops/src/algorithm/default_signing_algo.dart';
import 'package:at_chops/src/algorithm/ecc_signing_algo.dart';
import 'package:at_chops/src/algorithm/pkam_signing_algo.dart';
import 'package:at_chops/src/at_chops_base.dart';
import 'package:at_chops/src/key/at_key_pair.dart';
import 'package:at_chops/src/key/impl/aes_key.dart';
import 'package:at_chops/src/key/impl/at_chops_keys.dart';
import 'package:at_chops/src/key/impl/at_encryption_key_pair.dart';
import 'package:at_chops/src/key/key_names.dart';
import 'package:at_chops/src/key/key_type.dart';
Expand All @@ -27,7 +26,7 @@ import 'package:at_commons/at_commons.dart';
import 'package:at_utils/at_logger.dart';

class AtChopsImpl extends AtChops {
AtChopsImpl(AtChopsKeys atChopsKeys) : super(atChopsKeys);
AtChopsImpl(super.atChopsKeys);

final AtSignLogger _logger = AtSignLogger('AtChopsImpl');

Expand Down Expand Up @@ -143,74 +142,6 @@ class AtChopsImpl extends AtChops {
return hashingAlgorithm.hash(signedData);
}

@override
// ignore: deprecated_member_use_from_same_package
AtSigningResult signBytes(Uint8List data, SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm}) {
signingAlgorithm ??= _getSigningAlgorithm(signingKeyType)!;

// hard coding signing and hashing algo since this method is deprecated
final atSigningMetadata = AtSigningMetaData(SigningAlgoType.rsa2048,
HashingAlgoType.sha256, DateTime.now().toUtc());
final atSigningResult = AtSigningResult()
..atSigningMetaData = atSigningMetadata
..atSigningResultType = AtSigningResultType.bytes;
atSigningResult.result = signingAlgorithm.sign(data);
return atSigningResult;
}

@override
AtSigningResult verifySignatureBytes(
Uint8List data,
Uint8List signature,
// ignore: deprecated_member_use_from_same_package
SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm}) {
signingAlgorithm ??= _getSigningAlgorithm(signingKeyType)!;
// hard coding signing and hashing algo since this method is deprecated
final atSigningMetadata = AtSigningMetaData(SigningAlgoType.rsa2048,
HashingAlgoType.sha256, DateTime.now().toUtc());
final atSigningResult = AtSigningResult()
..atSigningMetaData = atSigningMetadata
..atSigningResultType = AtSigningResultType.bool;
atSigningResult.result = signingAlgorithm.verify(data, signature);
return atSigningResult;
}

@override
// ignore: deprecated_member_use_from_same_package
AtSigningResult signString(String data, SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm}) {
final signingResult = signBytes(
utf8.encode(data) as Uint8List, signingKeyType,
signingAlgorithm: signingAlgorithm);
final atSigningMetadata = signingResult.atSigningMetaData;
final atSigningResult = AtSigningResult()
..atSigningMetaData = atSigningMetadata
..atSigningResultType = AtSigningResultType.string;
atSigningResult.result = base64Encode(signingResult.result);
return atSigningResult;
}

@override
AtSigningResult verifySignatureString(
// ignore: deprecated_member_use_from_same_package
String data,
String signature,
// ignore: deprecated_member_use_from_same_package
SigningKeyType signingKeyType,
{AtSigningAlgorithm? signingAlgorithm}) {
final signingResult = verifySignatureBytes(
utf8.encode(data) as Uint8List, base64Decode(signature), signingKeyType,
signingAlgorithm: signingAlgorithm);
final atSigningMetadata = signingResult.atSigningMetaData;
final atSigningResult = AtSigningResult()
..atSigningMetaData = atSigningMetadata
..atSigningResultType = AtSigningResultType.bool;
atSigningResult.result = signingResult.result;
return atSigningResult;
}

@override
AtSigningResult sign(AtSigningInput signingInput) {
final dataBytes = _getBytes(signingInput.data);
Expand All @@ -221,7 +152,7 @@ class AtChopsImpl extends AtChops {
// change this method to public in the next major release and remove existing public method.
AtSigningResult _signBytes(Uint8List data, AtSigningInput signingInput,
{AtSigningAlgorithm? signingAlgorithm}) {
signingAlgorithm ??= _getSigningAlgorithmV2(signingInput)!;
signingAlgorithm ??= _getSigningAlgorithm(signingInput)!;
final atSigningMetadata = AtSigningMetaData(signingInput.signingAlgoType,
signingInput.hashingAlgoType, DateTime.now().toUtc());
final atSigningResult = AtSigningResult()
Expand Down Expand Up @@ -270,13 +201,11 @@ class AtChopsImpl extends AtChops {
EncryptionKeyType encryptionKeyType, String? keyName) {
switch (encryptionKeyType) {
case EncryptionKeyType.rsa2048:
return DefaultEncryptionAlgo(_getEncryptionKeyPair(keyName)!);
return RsaEncryptionAlgo.fromKeyPair(_getEncryptionKeyPair(keyName)!);
case EncryptionKeyType.rsa4096:
// TODO: Handle this case.
break;
throw AtEncryptionException('EncryptionKeyType.rsa4096 not supported');
case EncryptionKeyType.ecc:
// TODO: Handle this case.
break;
throw AtEncryptionException('EncryptionKeyType.ecc not supported');
case EncryptionKeyType.aes128:
return AESEncryptionAlgo(_getSymmetricKey(keyName)! as AESKey);
case EncryptionKeyType.aes256:
Expand All @@ -285,7 +214,6 @@ class AtChopsImpl extends AtChops {
throw AtEncryptionException(
'Cannot find encryption algorithm for encryption key type $encryptionKeyType');
}
return null;
}

AtEncryptionKeyPair? _getEncryptionKeyPair(String? keyName) {
Expand All @@ -305,25 +233,7 @@ class AtChopsImpl extends AtChops {
return null;
}

// ignore: deprecated_member_use_from_same_package
AtSigningAlgorithm? _getSigningAlgorithm(SigningKeyType signingKeyType) {
switch (signingKeyType) {
// ignore: deprecated_member_use_from_same_package
case SigningKeyType.pkamSha256:
return PkamSigningAlgo(
atChopsKeys.atPkamKeyPair!, HashingAlgoType.sha256);

// ignore: deprecated_member_use_from_same_package
case SigningKeyType.signingSha256:
return DefaultSigningAlgo(
atChopsKeys.atEncryptionKeyPair!, HashingAlgoType.sha256);
default:
throw AtSigningException(
'Cannot find signing algorithm for signing key type $signingKeyType');
}
}

AtSigningAlgorithm? _getSigningAlgorithmV2(AtSigningInput signingInput) {
AtSigningAlgorithm? _getSigningAlgorithm(AtSigningInput signingInput) {
if (signingInput.signingAlgorithm != null) {
return signingInput.signingAlgorithm;
} else if (signingInput.signingMode != null &&
Expand Down
Loading

0 comments on commit c0ea723

Please sign in to comment.