Signer
The @zintrust/signer package provides digital signature and verification capabilities for ZinTrust applications, enabling secure data integrity and authentication.
Installation
bash
npm install @zintrust/signerConfiguration
Add the signer configuration to your environment:
typescript
// config/signer.ts
import { SignerConfig } from '@zintrust/core';
export const signer: SignerConfig = {
default: 'rsa',
algorithms: {
rsa: {
keySize: 2048,
hashAlgorithm: 'sha256',
padding: 'pkcs1',
},
ecdsa: {
curve: 'p256',
hashAlgorithm: 'sha256',
},
ed25519: {
context: 'ZinTrust',
},
},
keyManagement: {
storage: 'file', // or 'vault', 'cloud'
path: './keys',
encryption: {
enabled: true,
algorithm: 'aes-256-gcm',
},
},
verification: {
cache: {
enabled: true,
ttl: 300000, // 5 minutes
maxSize: 1000,
},
strictMode: false,
},
};Environment Variables
bash
SIGNER_DEFAULT_ALGORITHM=rsa
SIGNER_KEY_STORAGE=file
SIGNER_KEY_PATH=./keys
SIGNER_KEY_ENCRYPTION=true
SIGNER_VERIFICATION_CACHE_TTL=300000Usage
typescript
import { Signer } from '@zintrust/core';
// Generate key pair
const keyPair = await Signer.generateKeyPair('rsa', {
keySize: 2048,
passphrase: 'secure-password',
});
// Sign data
const signature = await Signer.sign('rsa', keyPair.privateKey, 'Hello, World!');
// Verify signature
const isValid = await Signer.verify('rsa', keyPair.publicKey, 'Hello, World!', signature);
// Sign JSON data
const jsonData = { user: 'john', action: 'login' };
const jsonSignature = await Signer.signJSON('rsa', keyPair.privateKey, jsonData);
// Verify JSON signature
const isJsonValid = await Signer.verifyJSON('rsa', keyPair.publicKey, jsonData, jsonSignature);Features
- Multiple Algorithms: RSA, ECDSA, Ed25519 support
- Key Management: Secure key storage and management
- Data Signing: Sign strings, JSON, and binary data
- Signature Verification: Verify signatures with strict validation
- JSON Web Tokens: JWT creation and verification
- Timestamped Signatures: RFC 3161 timestamp support
- Batch Operations: Efficient batch signing and verification
- Security: Secure key generation and storage
Supported Algorithms
RSA (Rivest-Shamir-Adleman)
typescript
import { RSASigner } from '@zintrust/signer';
const rsaSigner = new RSASigner({
keySize: 2048, // 1024, 2048, 3072, 4096
hashAlgorithm: 'sha256', // sha1, sha256, sha384, sha512
padding: 'pkcs1', // pkcs1, pss
});
// Generate RSA key pair
const rsaKeyPair = await rsaSigner.generateKeyPair({
passphrase: 'secure-password',
format: 'pem', // pem, der, jwk
});
// Sign data
const signature = await rsaSigner.sign(rsaKeyPair.privateKey, 'Hello, World!');
// Verify signature
const isValid = await rsaSigner.verify(rsaKeyPair.publicKey, 'Hello, World!', signature);ECDSA (Elliptic Curve Digital Signature Algorithm)
typescript
import { ECDSASigner } from '@zintrust/signer';
const ecdsaSigner = new ECDSASigner({
curve: 'p256', // p256, p384, p521, secp256k1
hashAlgorithm: 'sha256', // sha1, sha256, sha384, sha512
});
// Generate ECDSA key pair
const ecdsaKeyPair = await ecdsaSigner.generateKeyPair({
format: 'pem',
});
// Sign data
const signature = await ecdsaSigner.sign(ecdsaKeyPair.privateKey, 'Hello, World!');
// Verify signature
const isValid = await ecdsaSigner.verify(ecdsaKeyPair.publicKey, 'Hello, World!', signature);Ed25519 (Edwards-curve Digital Signature Algorithm)
typescript
import { Ed25519Signer } from '@zintrust/signer';
const ed25519Signer = new Ed25519Signer({
context: 'ZinTrust', // Optional context string
});
// Generate Ed25519 key pair
const ed25519KeyPair = await ed25519Signer.generateKeyPair({
format: 'hex', // hex, base64, pem
});
// Sign data
const signature = await ed25519Signer.sign(ed25519KeyPair.privateKey, 'Hello, World!');
// Verify signature
const isValid = await ed25519Signer.verify(ed25519KeyPair.publicKey, 'Hello, World!', signature);Key Management
Key Storage
typescript
import { KeyManager } from '@zintrust/signer';
const keyManager = new KeyManager({
storage: 'file',
path: './keys',
encryption: {
enabled: true,
algorithm: 'aes-256-gcm',
key: 'encryption-key-32-bytes-long',
},
});
// Store key pair
await keyManager.storeKeyPair('user-signing-key', keyPair, {
passphrase: 'secure-password',
metadata: {
algorithm: 'rsa',
keySize: 2048,
created: new Date(),
purpose: 'user-signing',
},
});
// Retrieve key pair
const storedKeyPair = await keyManager.getKeyPair('user-signing-key', {
passphrase: 'secure-password',
});
// List keys
const keys = await keyManager.listKeys();
// Returns: Array<{ id: string, algorithm: string, created: Date, metadata: object }>
// Delete key
await keyManager.deleteKey('user-signing-key');Key Rotation
typescript
import { KeyRotation } from '@zintrust/signer';
const keyRotation = new KeyRotation(keyManager);
// Rotate key
const rotationResult = await keyRotation.rotate('user-signing-key', {
newAlgorithm: 'rsa',
newKeySize: 3072,
keepOldKey: true, // Keep old key for verification
transitionPeriod: 30 * 24 * 60 * 60 * 1000, // 30 days
});
// Get active key
const activeKey = await keyRotation.getActiveKey('user-signing-key');
// Verify with any key in rotation chain
const isValid = await keyRotation.verifyWithChain('user-signing-key', data, signature);Data Signing
String Data
typescript
// Sign simple string
const signature = await Signer.sign('rsa', privateKey, 'Hello, World!');
// Sign with options
const signatureWithOptions = await Signer.sign('rsa', privateKey, 'Hello, World!', {
encoding: 'utf8',
format: 'base64',
includeTimestamp: true,
});
// Sign with custom headers
const signatureWithHeaders = await Signer.sign('rsa', privateKey, 'Hello, World!', {
headers: {
'X-Algorithm': 'RSA-SHA256',
'X-Key-ID': 'user-signing-key',
'X-Timestamp': Date.now().toString(),
},
});JSON Data
typescript
// Sign JSON object
const jsonData = {
user: 'john@example.com',
action: 'login',
timestamp: new Date().toISOString(),
sessionId: 'abc123',
};
const jsonSignature = await Signer.signJSON('rsa', privateKey, jsonData, {
normalize: true, // Normalize JSON for consistent signing
includeHash: true, // Include data hash in signature
});
// Verify JSON signature
const isValid = await Signer.verifyJSON('rsa', publicKey, jsonData, jsonSignature, {
strictMode: true, // Strict field validation
allowExtraFields: false,
});Binary Data
typescript
import { BinarySigner } from '@zintrust/signer';
const binarySigner = new BinarySigner();
// Sign binary data
const fileBuffer = fs.readFileSync('document.pdf');
const signature = await binarySigner.sign('rsa', privateKey, fileBuffer, {
format: 'base64',
includeChecksum: true,
});
// Verify binary signature
const isValid = await binarySigner.verify('rsa', publicKey, fileBuffer, signature);JSON Web Tokens (JWT)
JWT Creation
typescript
import { JWTSigner } from '@zintrust/signer';
const jwtSigner = new JWTSigner({
algorithm: 'RS256',
keyPair: rsaKeyPair,
});
// Create JWT
const token = await jwtSigner.create({
payload: {
sub: 'user:123',
name: 'John Doe',
email: 'john@example.com',
role: 'user',
},
options: {
expiresIn: '1h',
issuer: 'ZinTrust',
audience: 'zintrust-app',
subject: 'user:123',
},
});
// Returns: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."JWT Verification
typescript
// Verify JWT
const payload = await jwtSigner.verify(token, {
algorithms: ['RS256'],
issuer: 'ZinTrust',
audience: 'zintrust-app',
clockTolerance: 30, // 30 seconds clock skew tolerance
});
// Returns: { sub: 'user:123', name: 'John Doe', email: 'john@example.com', role: 'user', iat: 1640995200, exp: 1640998800 }JWT Refresh
typescript
// Refresh token
const refreshedToken = await jwtSigner.refresh(token, {
expiresIn: '1h',
// Update payload if needed
payload: {
lastLogin: new Date().toISOString(),
},
});Timestamped Signatures
RFC 3161 Timestamps
typescript
import { TimestampedSigner } from '@zintrust/signer';
const timestampedSigner = new TimestampedSigner({
tsaUrl: 'http://timestamp.digicert.com',
hashAlgorithm: 'sha256',
});
// Create timestamped signature
const timestampedSignature = await timestampedSigner.sign(
'rsa',
privateKey,
'Important document content',
{
includeTimestamp: true,
tsaCredentials: {
username: 'tsa-user',
password: 'tsa-password',
},
}
);
// Verify timestamped signature
const verificationResult = await timestampedSigner.verify(
'rsa',
publicKey,
'Important document content',
timestampedSignature,
{
verifyTimestamp: true,
checkRevocation: true,
}
);
// Returns: { valid: boolean, timestamp: Date, verifiedAt: Date, revoked: boolean }Batch Operations
Batch Signing
typescript
import { BatchSigner } from '@zintrust/signer';
const batchSigner = new BatchSigner({
algorithm: 'rsa',
concurrency: 10,
});
// Prepare batch data
const batchData = [
{ id: 'doc1', content: 'Document 1 content' },
{ id: 'doc2', content: 'Document 2 content' },
{ id: 'doc3', content: 'Document 3 content' },
];
// Sign batch
const batchSignatures = await batchSigner.signBatch(privateKey, batchData, {
includeTimestamp: true,
format: 'base64',
});
// Returns: Array<{ id: string, signature: string, timestamp: Date }>Batch Verification
typescript
// Verify batch
const verificationResults = await batchSigner.verifyBatch(publicKey, batchData, batchSignatures, {
strictMode: true,
parallel: true,
});
// Returns: Array<{ id: string, valid: boolean, error?: string }>Security Features
Key Encryption
typescript
import { KeyEncryption } from '@zintrust/signer';
const keyEncryption = new KeyEncryption({
algorithm: 'aes-256-gcm',
key: 'encryption-key-32-bytes-long',
});
// Encrypt private key
const encryptedKey = await keyEncryption.encrypt(privateKey, {
passphrase: 'secure-password',
metadata: {
algorithm: 'rsa',
keySize: 2048,
},
});
// Decrypt private key
const decryptedKey = await keyEncryption.decrypt(encryptedKey, {
passphrase: 'secure-password',
});Secure Random
typescript
import { SecureRandom } from '@zintrust/signer';
// Generate secure random bytes
const randomBytes = await SecureRandom.bytes(32);
// Generate secure random string
const randomString = await SecureRandom.string(16, {
charset: 'alphanumeric', // hex, base64, alphanumeric
});
// Generate secure random integer
const randomInt = await SecureRandom.integer(1, 1000000);Performance Optimization
Signature Caching
typescript
import { SignatureCache } from '@zintrust/signer';
const signatureCache = new SignatureCache({
maxSize: 1000,
ttl: 300000, // 5 minutes
strategy: 'lru',
});
// Cache signature verification
const cacheKey = `${algorithm}:${hash(data)}`;
let isValid = await signatureCache.get(cacheKey);
if (isValid === undefined) {
isValid = await Signer.verify(algorithm, publicKey, data, signature);
await signatureCache.set(cacheKey, isValid);
}Parallel Processing
typescript
import { ParallelSigner } from '@zintrust/signer';
const parallelSigner = new ParallelSigner({
concurrency: 4,
chunkSize: 100,
});
// Sign large dataset in parallel
const largeDataset = Array.from({ length: 10000 }, (_, i) => `Data item ${i}`);
const signatures = await parallelSigner.signBatch(privateKey, largeDataset);Error Handling
Custom Error Handler
typescript
const signer = new Signer({
errorHandler: (error, operation, data) => {
console.log(`Signing error in ${operation}:`, error.message);
// Log to monitoring system
logError(error, { operation, dataSize: data?.length });
// Send alert for critical errors
if (error.severity === 'critical') {
sendAlert('Signing operation failed', error);
}
},
});Error Types
typescript
try {
await Signer.sign('rsa', privateKey, 'Hello, World!');
} catch (error) {
if (error.code === 'INVALID_KEY') {
console.log('Invalid private key format');
} else if (error.code === 'WEAK_KEY') {
console.log('Key size too small');
} else if (error.code === 'SIGNING_FAILED') {
console.log('Signing operation failed');
} else {
console.log('Signer error:', error.message);
}
}Testing
Mock Signer
typescript
import { SignerMock } from '@zintrust/signer';
// Use mock for testing
const mockSigner = new SignerMock({
algorithm: 'rsa',
signature: 'mock-signature',
verification: true,
});
// Test signing
const signature = await mockSigner.sign('rsa', privateKey, 'test-data');
expect(signature).toBe('mock-signature');
// Test verification
const isValid = await mockSigner.verify('rsa', publicKey, 'test-data', signature);
expect(isValid).toBe(true);Integration Testing
typescript
import { TestSigner } from '@zintrust/signer';
// Use test signer with known keys
const testSigner = new TestSigner({
algorithm: 'rsa',
keySize: 2048,
knownKeys: {
privateKey: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----',
publicKey: '-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----',
},
});
// Test with deterministic results
const signature = await testSigner.sign('rsa', testSigner.privateKey, 'test-data');
const isValid = await testSigner.verify('rsa', testSigner.publicKey, 'test-data', signature);
expect(isValid).toBe(true);Best Practices
- Key Security: Use strong key sizes and secure storage
- Algorithm Selection: Choose appropriate algorithms for your use case
- Key Rotation: Regularly rotate signing keys
- Timestamp Validation: Always validate timestamps when applicable
- Input Validation: Validate all inputs before signing
- Error Handling: Implement comprehensive error handling
- Performance: Use caching and batch operations for better performance
- Audit Trail: Maintain audit trail of all signing operations
Limitations
- Key Size: Maximum key size limitations
- Algorithm Support: Limited to supported algorithms
- Performance: Signing operations can be computationally expensive
- Storage: Encrypted keys require additional storage
- Network: Network-based verification may have latency
Troubleshooting
Common Issues
- Key Format Errors: Ensure keys are in correct format
- Algorithm Mismatch: Use same algorithm for signing and verification
- Encoding Issues: Ensure consistent encoding
- Memory Usage: Large data may cause memory issues
- Performance: Optimize for your specific use case
Debug Mode
typescript
export const signer: SignerConfig = {
default: 'rsa',
debug: process.env.NODE_ENV === 'development',
logging: {
level: 'debug',
logOperations: true,
logKeys: false, // Don't log actual keys
logPerformance: true,
},
};