encard
v1.1.1
Published
Enterprise-grade PCI-compliant frontend SDK for secure card data encryption
Maintainers
Readme
Encard - Card Encryption SDK
Encard is an enterprise-grade, PCI-compliant frontend SDK designed to securely encrypt sensitive card data before transmission to your backend services. Built with TypeScript and modern security practices, it provides robust client-side encryption using RSA-OAEP algorithms.
🔐 Key Features
- 🛡️ PCI-DSS Compliant: Designed with PCI-DSS requirements in mind
- 🔒 RSA-OAEP Encryption: Industry-standard RSA-OAEP-SHA256 encryption
- ✅ Card Validation: Comprehensive validation with Luhn algorithm
- 🏷️ Device Fingerprinting: Enhanced security with device identification
- 📊 Payload Tracking: Unique payload IDs for audit trails
- 🎯 TypeScript Native: Full type safety and modern development experience
- 🌐 Cross-Platform: Works in browsers, Node.js, and mobile web views
- 🔄 Backward Compatible: Maintains compatibility with existing implementations
📦 Installation
npm install encardyarn add encardpnpm add encard🚀 Quick Start
Basic Usage
import { CardEncryptor } from 'encard';
// Your RSA public key (2048-bit minimum recommended)
const publicKey = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;
// Card data to encrypt
const cardData = {
pan: '4111111111111111',
cvv: '123',
expiryMonth: '12',
expiryYear: '2025',
cardholderName: 'John Doe' // Optional
};
// Encrypt the card data
try {
const result = await CardEncryptor.encrypt(cardData, publicKey);
// Send encrypted data to your backend
const response = await fetch('/api/payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
encryptedCardData: result.encryptedData,
payloadId: result.payloadId,
deviceFingerprint: result.deviceFingerprint,
timestamp: result.timestamp
})
});
} catch (error) {
console.error('Encryption failed:', error.message);
}Advanced Usage with Configuration
import { CardEncryptor, CardValidator, DeviceFingerprint } from 'encard';
// Configure the encryptor
const encryptor = new CardEncryptor({
debug: true, // Enable debug logging
customValidation: (cardData) => {
// Add your custom validation logic
const baseValidation = CardValidator.validate(cardData);
// Example: Block specific BINs
if (cardData.pan.startsWith('4000')) {
return {
isValid: false,
errors: ['This card type is not accepted']
};
}
return baseValidation;
}
});
// Generate device fingerprint
const deviceFingerprint = await DeviceFingerprint.generate();
// Encrypt with advanced options
const result = await encryptor.encryptCardData(cardData, {
publicKey,
payloadId: 'custom-transaction-id-123',
deviceFingerprint,
timestamp: Date.now()
});Validation Only
import { CardValidator } from 'encard';
const validation = CardValidator.validate(cardData);
if (!validation.isValid) {
console.log('Validation errors:', validation.errors);
// Handle validation errors in your UI
}
// Detect card brand
const brand = CardValidator.detectCardBrand(cardData.pan);
console.log('Card brand:', brand); // 'visa', 'mastercard', 'amex', etc.🏗️ API Reference
CardEncryptor
CardEncryptor.encrypt(cardData, publicKey, options?)
Static method for simple encryption.
Parameters:
cardData: CardData- Card information to encryptpublicKey: string- RSA public key in PEM formatoptions?: Partial<EncryptionOptions>- Optional encryption settings
Returns: Promise<EncryptedPayload>
new CardEncryptor(config?)
Create a new encryptor instance with configuration.
Parameters:
config?: SDKConfig- SDK configuration options
CardValidator
CardValidator.validate(cardData)
Validates complete card data.
Parameters:
cardData: CardData- Card data to validate
Returns: ValidationResult
CardValidator.detectCardBrand(pan)
Detects card brand from PAN.
Parameters:
pan: string- Primary Account Number
Returns: string - Card brand ('visa', 'mastercard', 'amex', 'discover', 'jcb', 'unknown')
DeviceFingerprint
DeviceFingerprint.generate()
Generates a comprehensive device fingerprint.
Returns: Promise<string>
DeviceFingerprint.generateLightweight()
Generates a lightweight fingerprint for restricted environments.
Returns: string
📋 Type Definitions
interface CardData {
readonly pan: string; // Primary Account Number
readonly cvv: string; // Card Verification Value
readonly expiryMonth: string; // MM format
readonly expiryYear: string; // YYYY format
readonly cardholderName?: string; // Optional
}
interface EncryptedPayload {
readonly encryptedData: string; // Base64 encrypted data
readonly algorithm: 'RSA-OAEP-SHA256';
readonly timestamp: number; // Unix timestamp
readonly version: string; // SDK version
readonly payloadId?: string; // Unique identifier
readonly deviceFingerprint?: string; // Device fingerprint
}
interface ValidationResult {
readonly isValid: boolean;
readonly errors: readonly string[];
}🔒 Security Considerations
PCI-DSS Compliance
- Data Minimization: Only encrypt necessary card data
- Key Management: Use strong RSA keys (minimum 2048-bit)
- Secure Transmission: Always use HTTPS for data transmission
- Key Rotation: Implement regular key rotation policies
- Audit Trails: Utilize payload IDs for transaction tracking
Best Practices
- Never log decrypted card data
- Validate all input data before encryption
- Use device fingerprinting for fraud detection
- Implement proper error handling
- Keep the SDK updated to the latest version
Key Requirements
- Minimum 2048-bit RSA keys
- Keys must be in PEM format
- Public key validation is performed automatically
🧪 Testing
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run linting
npm run lintKey Rotation Support
// Handle key rotation gracefully
const encryptWithFallback = async (cardData, primaryKey, fallbackKey) => {
try {
return await CardEncryptor.encrypt(cardData, primaryKey);
} catch (error) {
if (error.code === 'INVALID_PUBLIC_KEY') {
return await CardEncryptor.encrypt(cardData, fallbackKey);
}
throw error;
}
};Audit Trail Implementation
const auditLog = {
payloadId: result.payloadId,
deviceFingerprint: result.deviceFingerprint,
timestamp: result.timestamp,
cardBrand: CardValidator.detectCardBrand(cardData.pan),
lastFourDigits: cardData.pan.slice(-4)
};
// Send audit information to your logging service
await logSecurityEvent('card_encryption', auditLog);Error Handling
try {
const result = await CardEncryptor.encrypt(cardData, publicKey);
} catch (error) {
if (error instanceof ValidationError) {
// Handle validation errors
displayValidationErrors(error.errors);
} else if (error instanceof EncryptionError) {
// Handle encryption errors
handleEncryptionFailure(error.code, error.details);
} else {
// Handle unexpected errors
reportUnexpectedError(error);
}
}🔧 Development & Contribution
Building from Source
# Clone the repository
git clone https://github.com/your-username/encard.git
cd encard
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm testCI/CD Pipeline
The project includes configuration for:
- TypeScript compilation
- ESLint code quality checks
- Vitest unit testing
- Coverage reporting
- Automated builds
📄 License
MIT License - see the LICENSE file for details.
🤝 Contributing
We welcome contributions! Please see our Contributing Guidelines for details.
🐛 Issues & Support
- Bug Reports: GitHub Issues
- Feature Requests: GitHub Discussions
⚠️ Security Notice: This SDK handles sensitive payment card data. Always ensure you're compliant with PCI-DSS requirements and your local data protection regulations.
Built with ❤️ for secure payments
