Skip to main content

affinidi_tsp_pq 0.1.1 copy "affinidi_tsp_pq: ^0.1.1" to clipboard
affinidi_tsp_pq: ^0.1.1 copied to clipboard

Post-quantum key types for affinidi_tsp: the MLKEM768-X25519 hybrid HPKE KEM (0x647a) and ML-DSA-65 signatures, on the pure-Dart pqcrypto package.

example/affinidi_tsp_pq_example.dart

// Two parties with post-quantum keys exchange a confidential TSP message.
//
// Post-quantum support is not a separate mode: the receiver's MLKEM768-X25519
// encryption key selects the hybrid KEM (0x647a) and the sender's ML-DSA-65
// signing key selects the signature algorithm (1AAQ). The wire format is the
// same HPKE-Base scheme the classical keys use.
//
//   dart run example/affinidi_tsp_pq_example.dart

import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

import 'package:affinidi_tsp/affinidi_tsp.dart';
import 'package:affinidi_tsp_pq/affinidi_tsp_pq.dart';
import 'package:pqcrypto/pqcrypto.dart';

Uint8List randomBytes(int length) {
  final random = Random.secure();
  return Uint8List.fromList([
    for (var i = 0; i < length; i++) random.nextInt(256),
  ]);
}

({PrivateVid private, PublicVid public}) createIdentity(String id) {
  // ML-DSA-65 for signing.
  final (verificationKey, signingKey) = MlDsa.generateKeyPair(
    DilithiumParams.mlDsa65,
  );

  // MLKEM768-X25519 for encryption. The 32-byte seed is the whole private key.
  final seed = MlKem768X25519.deriveSecretKey(randomBytes(32));
  final decryptionKey = MlKem768X25519DecryptionKey.fromSeed(seed);

  return (
    private: PrivateVid(
      id: id,
      signingKey: MlDsa65SigningKey(signingKey),
      decryptionKey: decryptionKey,
    ),
    public: PublicVid(
      id: id,
      verificationKey: MlDsa65VerificationKey(verificationKey),
      encryptionKey: MlKem768X25519EncryptionKey(decryptionKey.publicKey),
    ),
  );
}

Future<void> main() async {
  final alice = createIdentity('did:example:alice');
  final bob = createIdentity('did:example:bob');

  final packed = await Tsp.pack(
    sender: alice.private,
    receiver: bob.public,
    payload: ScsPayload(utf8.encode('hello over post-quantum TSP')),
  );
  stdout.writeln('Sealed ${packed.bytes.length} bytes');

  final opened = await Tsp.open(
    packed.bytes,
    receiver: bob.private,
    sender: alice.public,
  );
  final payload = opened.payload as ScsPayload;
  stdout.writeln('Negotiated KEM: 0x${opened.kem?.id.toRadixString(16)}');
  stdout.writeln('Bob read: ${utf8.decode(payload.data)}');

  // Resolving post-quantum VIDs from real DID documents needs the key mapper,
  // which reads the provisional Multikey codecs the ToIP implementation
  // writes. Pass it wherever a resolver is constructed.
  final resolver = SsiVidResolver(keyMappers: const [PostQuantumKeyMapper()]);
  stdout.writeln(
    'Resolver understands ML-DSA-65 and MLKEM768-X25519: '
    '${resolver.keyMappers.length} mapper(s)',
  );
}
0
likes
160
points
429
downloads

Documentation

API reference

Publisher

verified publisheraffinidi.com

Weekly Downloads

Post-quantum key types for affinidi_tsp: the MLKEM768-X25519 hybrid HPKE KEM (0x647a) and ML-DSA-65 signatures, on the pure-Dart pqcrypto package.

Repository (GitHub)
View/report issues
Contributing

License

Apache-2.0 (license)

Dependencies

affinidi_tsp, pqcrypto, ssi

More

Packages that depend on affinidi_tsp_pq