Skip to content

4.2 Cryptographic Mitigations and Key Management

The integrity of the entire system rests on the security of the Canton Policy Issuer's private key. Canton supports robust cryptographic schemes and mandates professional key management practices.

Supported Cryptographic Schemes

Canton supports industry-standard cryptographic algorithms:

AlgorithmKey SizeUse CaseSecurity Level
Ed25519256-bitDefault signingHigh (128-bit security)
ECDSA P-256256-bitEVM compatibilityHigh (128-bit security)
ECDSA secp256k1256-bitBitcoin/EthereumHigh (128-bit security)

Key Management Architecture

Policy Issuer Key Protection

┌──────────────────────────────────────────┐
│   Hardware Security Module (HSM)         │
│                                          │
│  ┌────────────────────────────────────┐ │
│  │    Policy Issuer Private Key       │ │
│  │    (Never leaves HSM)              │ │
│  └────────────────────────────────────┘ │
│                                          │
│  ┌────────────────────────────────────┐ │
│  │    Signing Operations              │ │
│  │    • Sign ExecutionIntent          │ │
│  │    • Sign Policy Updates           │ │
│  │    • Audit Logging                 │ │
│  └────────────────────────────────────┘ │
└──────────────────────────────────────────┘

         │ Signed Intents

┌────────▼──────────────────────────────────┐
│   Canton Participant Node                 │
│   • Public key known to network           │
│   • Signature verification                │
└───────────────────────────────────────────┘

Key Lifecycle Management

1. Key Generation

bash
# Generate key in HSM (example with AWS KMS)
aws kms create-key \
  --description "Canton Policy Issuer Key" \
  --key-usage SIGN_VERIFY \
  --key-spec ECC_NIST_P256

# Export public key
aws kms get-public-key --key-id $KEY_ID

2. Key Registration

daml
-- Register public key in Canton topology
topology.transactions.add_signing_key(
  party = "PolicyIssuer",
  public_key = "0x...",
  key_purpose = SigningKeyPurpose.Policy
)

3. Key Rotation

typescript
async function rotateKey(): Promise<void> {
  // 1. Generate new key in HSM
  const newKeyId = await hsm.generateKey({
    algorithm: 'ECDSA_P256',
    label: 'PolicyIssuer_v2'
  });

  // 2. Register new key in Canton
  await canton.topology.addKey({
    party: policyIssuerParty,
    publicKey: await hsm.getPublicKey(newKeyId)
  });

  // 3. Update on-chain registry (Pattern 2)
  await keyRegistry.registerKey(
    policyIssuerParty,
    await hsm.getPublicKey(newKeyId)
  );

  // 4. Deprecate old key (after grace period)
  await canton.topology.revokeKey({
    party: policyIssuerParty,
    publicKey: oldPublicKey
  });
}

4. Key Backup and Recovery

Backup Strategy:
- HSM key material encrypted and stored in cold storage
- Multi-party key recovery (e.g., Shamir's Secret Sharing)
- Geographic redundancy
- Regular backup verification

Intent Signature Generation

Canton Side

daml
-- Sign ExecutionIntent payload
signIntent : ExecutionIntent -> Update Text
signIntent intent = do
  let payload = serializeIntent intent
  let hash = sha256 payload

  -- Sign with Canton's HSM-backed key
  signature <- signWithHSM hash

  return $ base64Encode signature

Verification on Public Chain (Pattern 2)

solidity
function verifyCantonSignature(
    bytes calldata intentPayload,
    bytes calldata signature
) internal view returns (bool) {
    // 1. Hash the intent payload
    bytes32 payloadHash = keccak256(intentPayload);

    // 2. Prepare Ethereum signed message hash
    bytes32 ethSignedHash = keccak256(
        abi.encodePacked(
            "\x19Ethereum Signed Message:\n32",
            payloadHash
        )
    );

    // 3. Recover signer address
    address recoveredSigner = _ecrecover(ethSignedHash, signature);

    // 4. Verify against Canton Key Registry
    address authorizedKey = keyRegistry.cantonPartyToKey(
        authorizedPartyId
    );

    return recoveredSigner == authorizedKey;
}

function _ecrecover(
    bytes32 hash,
    bytes memory signature
) internal pure returns (address) {
    require(signature.length == 65, "Invalid signature length");

    bytes32 r;
    bytes32 s;
    uint8 v;

    assembly {
        r := mload(add(signature, 32))
        s := mload(add(signature, 64))
        v := byte(0, mload(add(signature, 96)))
    }

    if (v < 27) v += 27;

    require(v == 27 || v == 28, "Invalid signature v value");

    return ecrecover(hash, v, r, s);
}

Multi-Signature Schemes

For enhanced security, implement multi-signature authorization:

Canton Multi-Party Approval

daml
template MultiSigPolicy
  with
    signers: [Party]
    threshold: Int
  where
    signatory signers

    choice CollectSignatures : ContractId ExecutionIntent
      with
        intent: ExecutionIntent
        signatures: [Signature]
      controller head signers
      do
        -- Verify threshold met
        assertMsg "Threshold not met"
          (length signatures >= threshold)

        -- Verify each signature
        forA_ signatures $ \sig ->
          assertMsg "Invalid signature"
            (verifySignature sig intent)

        -- Create authorized intent
        create intent

On-Chain Multi-Sig Verification

solidity
contract MultiSigVault {
    address[] public cantonSigners;
    uint256 public threshold;

    function executeIntent(
        bytes calldata intentPayload,
        bytes[] calldata signatures
    ) external {
        require(
            signatures.length >= threshold,
            "Insufficient signatures"
        );

        bytes32 intentHash = keccak256(intentPayload);

        // Verify each signature
        uint256 validSignatures = 0;
        for (uint i = 0; i < signatures.length; i++) {
            address signer = _recoverSigner(intentHash, signatures[i]);

            if (_isAuthorizedSigner(signer)) {
                validSignatures++;
            }
        }

        require(
            validSignatures >= threshold,
            "Threshold not met"
        );

        // Execute...
    }
}

Non-Repudiation

All signatures provide cryptographic non-repudiation:

Properties:

  • Signer cannot deny signing the intent
  • Third parties can verify signature authenticity
  • Immutable audit trail on Canton ledger
  • Time-stamped with Canton's logical clock

Verification Process:

1. Retrieve intent from public chain
2. Fetch Canton's public key from registry
3. Verify signature: ecrecover(hash(intent), signature) == canton_pubkey
4. Cross-reference with Canton ledger for authorization proof

Best Practices

1. Key Storage

  • [ ] Use HSM or KMS for all production keys
  • [ ] Never store private keys in code or configuration files
  • [ ] Implement key access logging
  • [ ] Regular security audits of key management infrastructure

2. Key Rotation

  • [ ] Establish regular rotation schedule (e.g., quarterly)
  • [ ] Automated rotation procedures
  • [ ] Grace period for old key deprecation
  • [ ] Test rotation in staging environment first

3. Access Control

  • [ ] Multi-factor authentication for HSM access
  • [ ] Principle of least privilege
  • [ ] Separate keys for different environments (dev/staging/prod)
  • [ ] Regular access review

4. Monitoring

  • [ ] Alert on unusual signing patterns
  • [ ] Track signature failure rates
  • [ ] Monitor key usage frequency
  • [ ] Log all key management operations

Compliance Considerations

FIPS 140-2/140-3

For regulated institutions, use FIPS-validated HSMs:

  • Level 2: Role-based authentication, tamper-evident seals
  • Level 3: Tamper-responsive, identity-based authentication
  • Level 4: Complete envelope protection, environmental failure protection

eIDAS (EU)

For EU institutions, ensure compliance with eIDAS regulation:

  • Qualified electronic signatures
  • Qualified trust service providers
  • Audit trail requirements
  • Cross-border recognition

Canton DeFi - Multichain DeFi Technical Reference