πŸ” Cryptographic Block Signatures

Sign your blocks to guarantee authenticity and non-repudiation

πŸ“¦ Package NPM @sowasit/signerπŸ“š API Reference

Introduction

SoWasIt allows you to cryptographically sign your blocks to guarantee their authenticity and non-repudiation. Using a Public Key Infrastructure (PKI) with ECDSA P-256 algorithms, you can prove that your organization created a specific block.

πŸ’‘ Use Cases :
  • Regulatory compliance (qualified electronic signature)
  • Legal proof of data creation
  • Enhanced audit trail and traceability
  • Transaction non-repudiation

Why have a partner sign?

Real-world scenario: a delivery dispute

TechCorp sources components from SupplyPro and manages its deliveries in a SoWasIt chain. Here is what happens depending on whether SupplyPro signs the blocks or not.

❌ Without partner signature β€” the problem

On January 15th, SupplyPro makes a delivery. TechCorp records the block itself: "Delivery received: 500 units, ref. ABC-789". SupplyPro signs the paper delivery note as usual and leaves.

Three months later, SupplyPro sends an invoice for 800 units, claiming that is what they delivered. TechCorp shows its blocks stating "500 units"... but SupplyPro argues that TechCorp created those blocks. Nothing prevented TechCorp from entering 500 instead of 800 to reduce its invoice. It's their word against each other's.

The problem: if you are the one recording data on behalf of your partner, nothing proves that the partner agreed with what you wrote.

βœ… With partner signature β€” the solution

SupplyPro generates its ECDSA key pair using @sowasit/signer and registers it with TechCorp. From now on, for each delivery, it is SupplyPro's own system that creates and signs the block: "Delivery confirmed: 500 units, ref. ABC-789".

Three months later, SupplyPro still sends an invoice for 800 units. TechCorp pulls up the block signed by SupplyPro itself attesting to 500 units delivered. SupplyPro's cryptographic signature is there, verifiable and irrevocable. SupplyPro cannot claim to have delivered 800 β€” its own signature says 500.

In the event of a dispute, TechCorp presents the blocks signed by SupplyPro. The proof is cryptographically irrefutable and legally enforceable: SupplyPro itself certified the figure.

Other use cases

The same principle applies across many industries:

  • A carrier signs delivery notes in your logistics chain
  • A certification body signs your quality audit blocks
  • A contractor signs their service reports in your CMMS
  • A customer signs their order or receipt validation
  • A financial partner signs payment confirmations
In short: the real value of signatures comes from the fact that a trusted third party β€” not you β€” stamps the data. This turns your chain into bilateral proof, enforceable against both sides.

Key Lifecycle

1️⃣ Enrollment token generation β†’ Chain owner generates a token for a partner
2️⃣ Key pair generation β†’ Partner uses the CLI to create ECDSA keys
3️⃣ Public key registration β†’ Partner sends public key to SoWasIt
4️⃣ Certification β†’ Partner prints, signs and uploads the certification document
5️⃣ Verification β†’ Chain owner verifies the partner's document
6️⃣ Activation β†’ Chain owner activates the key, partner can sign blocks
7️⃣ Revocation (if needed) β†’ Chain owner revokes a compromised or obsolete key

CLI Installation

The @sowasit/signer package is available on NPM and can be used as a CLI tool or JavaScript/TypeScript library.

Global installation (CLI)

npm install -g @sowasit/signer

Local installation (library)

npm install @sowasit/signer

Quick Start

1. Generate and register a key pair (Partner)

First, get an enrollment token from the chain owner, then:

signer add-key \
  --token YOUR_ENROLLMENT_TOKEN \
  --api-key YOUR_API_KEY \
  --passphrase your-secret-passphrase \
  --output ./keys \
  --client-name "Your Company Name" \
  --client-contact "admin@company.com"

This command will:

  • Generate an ECDSA P-256 key pair
  • Register the public key with SoWasIt
  • Save the keys locally in ./keys/
  • Generate a certification document to print, sign and upload

2. Complete certification (Partner)

⚠️ Required step: To allow the chain owner to activate your key, you must:
  1. Print the generated certification document (sowasit.certification.txt)
  2. Sign and stamp it (legal signature of your company)
  3. Scan it as PDF
  4. Upload it via the API or dashboard

3. Create a signed block (Partner)

Once the chain owner has activated your key (status = active), you can sign blocks:

signer create-block \
  --chain ch_abc123 \
  --key ./keys/sowasit.private.pem \
  --key-id f1a2b3c4d5e6f7g8 \
  --api-key sk_your_api_key \
  --content-file ./data.json \
  --passphrase your-secret-passphrase

CLI Reference

signer add-key

Generate a new key pair and register it with SoWasIt.

OptionDescriptionRequired
-t, --tokenEnrollment token from SoWasItβœ“
-k, --api-keyYour SoWasIt API keyβœ“
-o, --outputOutput directory (default: ./keys)
-p, --passphrasePassphrase to encrypt private keyRecommended
--client-nameYour company name
--client-contactContact email

signer sign

Sign content with your private key (without creating a block).

signer sign \
  --key ./keys/sowasit.private.pem \
  --data ./content.json \
  --passphrase secret \
  --output ./signature.json

signer create-block

Create a signed block directly on SoWasIt.

signer create-block \
  --chain ch_abc123 \
  --key ./keys/sowasit.private.pem \
  --key-id f1a2b3c4 \
  --api-key sk_xxx \
  --content '{"order": "ORD-001", "status": "shipped"}' \
  --passphrase secret

Programmatic Usage (JavaScript/TypeScript)

Generate a key pair

import { KeyManager } from '@sowasit/signer';

// Generate key pair
const keyPair = await KeyManager.generateKeyPair({
  passphrase: 'your-secret-passphrase'
});

// Save to disk
await KeyManager.saveKeyPair(keyPair, './keys', 'my-company');

console.log('Key ID:', keyPair.keyId);
console.log('Fingerprint:', keyPair.fingerprint);

Sign content

import { KeyManager } from '@sowasit/signer';

const content = {
  transaction_id: 'TXN-001',
  amount: 1500.00,
  timestamp: Date.now()
};

const privateKey = await KeyManager.loadPrivateKey(
  './keys/my-company.private.pem',
  'your-passphrase'
);

const { signature, algorithm } = KeyManager.signContent(
  content,
  privateKey
);

console.log('Signature:', signature);

Create a signed block

import { SoWasItClient } from '@sowasit/signer';
import fs from 'node:fs/promises';

const client = new SoWasItClient({
  apiKey: 'sk_your_api_key'
});

const content = {
  event: 'product_shipped',
  order_id: 'ORD-12345',
  timestamp: Date.now()
};

const privateKeyPem = await fs.readFile('./keys/my-company.private.pem', 'utf-8');

const response = await client.createSignedBlock(
  'ch_your_chain_id',
  content,
  privateKeyPem,
  'your_public_key_id',
  'your-passphrase'
);

console.log('Block created:', response.block);

Security Best Practices

πŸ”’ Private Key Protection

  • Always use a passphrase to encrypt your private key
  • Never commit private keys to Git
  • Store keys in a password manager or HSM
  • Private keys are automatically saved with 0600 permissions

πŸ”„ Key Rotation

  • Generate new keys regularly (every 6-12 months)
  • Use the replacement mechanism during rotation
  • Revoke old keys after migration

⚠️ In Case of Compromise

  • Immediately revoke the compromised key
  • Generate a new key pair
  • Notify the SoWasIt team if necessary

API Endpoints

POST /keys/enrollment-tokens

Generate a one-time enrollment token (7 days validity).

curl -X POST https://api.sowasit.io/keys/enrollment-tokens \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "metadata": {
      "authorized_by": "admin@company.com"
    },
    "validity_days": 7
  }'

POST /keys/register

Register a public key with an enrollment token.

curl -X POST https://api.sowasit.io/keys/register \
  -H "Content-Type: application/json" \
  -d '{
    "enrollment_token": "abc123...",
    "public_key": "-----BEGIN PUBLIC KEY-----\n...",
    "algorithm": "ECDSA-P-256",
    "client_info": {
      "name": "My Company SARL",
      "siret": "12345678901234",
      "contact": "admin@company.com"
    }
  }'

GET /keys

List all your public keys.

curl https://api.sowasit.io/keys \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /keys/{keyId}/revoke

Revoke a public key.

curl -X POST https://api.sowasit.io/keys/abc123/revoke \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Key compromised"
  }'

Troubleshooting

❌ "Block signature is required: tenant has active public keys"

Your tenant has registered active keys, so all blocks must be signed.

Solution: Use signer create-block or manually sign with signer sign.

❌ "Invalid passphrase for encrypted private key"

Your key is encrypted but you provided the wrong passphrase or no passphrase.

Solution: Provide the correct passphrase with --passphrase.

❌ "Invalid block signature"

Signature verification failed.

Possible causes:

  • Content was modified after signing
  • Wrong private key used
  • Invalid signature format
  • Public key ID does not match the signing key

❌ "Public key is not active"

The key is not yet activated or has been revoked.

Solution: Check the key status in your dashboard. Complete certification if necessary.

Support