Mastering cryptographic foundations for content authentication and verification
Digital signatures form the backbone of content authentication. They provide mathematical proof that content was created or endorsed by a specific entity and hasn't been altered since signing. Unlike physical signatures, digital signatures cannot be forged without access to the private key.
The security of digital signatures relies on asymmetric cryptography, where each entity possesses a key pair: a private key kept secret and a public key shared openly. Content signed with the private key can be verified by anyone with the corresponding public key.
PKI provides the framework for managing cryptographic keys and certificates. In content authentication:
// Example: Generating Ed25519 Key Pair
import { generateKeyPairSync } from 'crypto';
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
console.log('Public Key:', publicKey);
console.log('Private Key:', privateKey);
// Store private key securely (e.g., hardware security module)
storeInHSM(privateKey);
// Publish public key for verification
publishPublicKey(publicKey);
WIA-AI-017 supports multiple signature algorithms, each with different security properties and performance characteristics.
Ed25519 is the recommended algorithm for most content authentication scenarios:
// Example: Signing Content with Ed25519
import { sign, createHash } from 'crypto';
import { readFileSync } from 'fs';
// Load content
const content = readFileSync('image.jpg');
// Hash the content first (best practice)
const contentHash = createHash('sha256').update(content).digest();
// Sign the hash
const signature = sign(null, contentHash, {
key: privateKey,
format: 'pem'
});
// Create authentication manifest
const manifest = {
content_hash: contentHash.toString('hex'),
signature: signature.toString('base64'),
algorithm: 'Ed25519',
signer_public_key: publicKey,
timestamp: new Date().toISOString(),
standard: 'WIA-AI-017'
};
console.log('Authentication Manifest:', JSON.stringify(manifest, null, 2));
ECDSA with P-256 or P-384 curves provides flexibility and wide compatibility:
// Example: ECDSA Signing
const { privateKey, publicKey } = generateKeyPairSync('ec', {
namedCurve: 'P-256',
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
const signature = sign('sha256', contentHash, {
key: privateKey,
dsaEncoding: 'ieee-p1363'
});
RSA-PSS is recommended when compatibility with legacy systems is required:
Cryptographic hash functions convert content of any size into fixed-size digests. For content authentication, hash functions must be:
WIA-AI-017 mandates SHA-256 or SHA-3 for content hashing:
| Algorithm | Output Size | Security | Speed |
|---|---|---|---|
| SHA-256 | 256 bits | 128-bit | Fast (hardware acceleration) |
| SHA-3-256 | 256 bits | 128-bit | Moderate |
| SHA-512 | 512 bits | 256-bit | Fast on 64-bit systems |
// Example: Multi-algorithm Hashing
import { createHash } from 'crypto';
function computeContentHash(content, algorithm = 'sha256') {
const hash = createHash(algorithm);
hash.update(content);
return {
algorithm: algorithm,
hash: hash.digest('hex'),
length: hash.digest().length * 8
};
}
// Generate multiple hashes for redundancy
const hashes = {
primary: computeContentHash(content, 'sha256'),
secondary: computeContentHash(content, 'sha3-256'),
fallback: computeContentHash(content, 'sha512')
};
Verification is the inverse of signing. The verifier uses the signer's public key to confirm the signature is valid for the content.
// Example: Complete Verification Flow
import { verify, createHash } from 'crypto';
function verifyContentAuthenticity(content, manifest) {
// Step 1: Compute content hash
const computedHash = createHash('sha256')
.update(content)
.digest('hex');
// Step 2: Check hash matches manifest
if (computedHash !== manifest.content_hash) {
return {
valid: false,
reason: 'Content has been modified',
hash_match: false
};
}
// Step 3: Verify signature
try {
const isValid = verify(
null,
Buffer.from(manifest.content_hash, 'hex'),
{
key: manifest.signer_public_key,
format: 'pem'
},
Buffer.from(manifest.signature, 'base64')
);
return {
valid: isValid,
reason: isValid ? 'Signature valid' : 'Invalid signature',
hash_match: true,
signer: extractSignerInfo(manifest.signer_public_key),
timestamp: manifest.timestamp
};
} catch (error) {
return {
valid: false,
reason: 'Verification error: ' + error.message,
hash_match: true
};
}
}
// Usage
const verificationResult = verifyContentAuthenticity(content, manifest);
console.log('Verification Result:', verificationResult);
X.509 certificates bind public keys to identities. In content authentication, certificates prove who signed the content.
An X.509 certificate contains:
// Example: Certificate Validation
import { X509Certificate } from 'crypto';
function validateCertificate(certPEM) {
const cert = new X509Certificate(certPEM);
// Check validity period
const now = new Date();
const notBefore = new Date(cert.validFrom);
const notAfter = new Date(cert.validTo);
if (now < notBefore || now > notAfter) {
throw new Error('Certificate expired or not yet valid');
}
// Check key usage
const keyUsage = cert.keyUsage;
if (!keyUsage.includes('digitalSignature')) {
throw new Error('Certificate not authorized for digital signatures');
}
// Verify certificate chain
const issuerCert = loadIssuerCertificate(cert.issuer);
if (!cert.verify(issuerCert.publicKey)) {
throw new Error('Certificate signature invalid');
}
// Check revocation
if (isCertificateRevoked(cert.serialNumber)) {
throw new Error('Certificate has been revoked');
}
return {
valid: true,
subject: cert.subject,
issuer: cert.issuer,
validFrom: cert.validFrom,
validTo: cert.validTo
};
}
RFC 3161 timestamps prove when content was signed, preventing backdating attacks and establishing signature creation time.
A TSA is a trusted third party that:
// Example: Requesting Timestamp Token
async function getTimestamp(signature) {
const signatureHash = createHash('sha256')
.update(signature)
.digest();
// Create timestamp request
const tsRequest = {
version: 1,
messageImprint: {
hashAlgorithm: 'sha256',
hashedMessage: signatureHash
},
certReq: true,
nonce: generateNonce()
};
// Send to TSA
const response = await fetch('https://tsa.example.com/timestamp', {
method: 'POST',
headers: { 'Content-Type': 'application/timestamp-query' },
body: encodeTSRequest(tsRequest)
});
const tsToken = await response.arrayBuffer();
// Verify timestamp token
const timestamp = parseTimestampToken(tsToken);
return {
timestamp: timestamp.genTime,
tsa: timestamp.tsa,
serial: timestamp.serialNumber
};
}
Private keys must be protected from theft or misuse. Hardware Security Modules provide tamper-resistant key storage and signing operations.
WIA-AI-017 supports multiple signature container formats:
CMS is the standard format for signed data, defined in RFC 5652. It supports:
JWS provides a JSON-based signature format, ideal for web applications:
// Example: Creating JWS
import { createSign } from 'crypto';
function createJWS(payload, privateKey) {
// Header
const header = {
alg: 'EdDSA',
typ: 'WIA-AUTH',
kid: computeKeyId(publicKey)
};
// Encode header and payload
const encodedHeader = base64url(JSON.stringify(header));
const encodedPayload = base64url(JSON.stringify(payload));
// Sign
const signingInput = `${encodedHeader}.${encodedPayload}`;
const signature = sign(null, Buffer.from(signingInput), privateKey);
const encodedSignature = base64url(signature);
// Return compact serialization
return `${signingInput}.${encodedSignature}`;
}
// Usage
const jws = createJWS({
content_hash: contentHash,
timestamp: new Date().toISOString(),
standard: 'WIA-AI-017'
}, privateKey);
Current signature algorithms (Ed25519, ECDSA, RSA) are vulnerable to quantum computers. WIA-AI-017 provides migration guidance for post-quantum cryptography.
Recommended quantum-resistant algorithms:
Secure signature implementation requires attention to multiple details:
弘益人間 (홍익인간) · Benefit All Humanity