Card Encryption
Flow

Encryption Code
Download and simulate the encryption without installing a programming language
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Card Encryption</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: bold;
}
input[type="text"],
input[type="number"],
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
box-sizing: border-box;
}
input[type="text"]:focus,
input[type="number"]:focus,
textarea:focus {
outline: none;
border-color: #4CAF50;
}
.row {
display: flex;
gap: 15px;
}
.col {
flex: 1;
}
.btn {
background-color: #4CAF50;
color: white;
padding: 12px 30px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
width: 100%;
margin-top: 20px;
}
.btn:hover {
background-color: #45a049;
}
.btn:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.result {
margin-top: 20px;
padding: 15px;
background-color: #f9f9f9;
border-radius: 5px;
border: 1px solid #ddd;
}
.error {
color: #d32f2f;
background-color: #ffebee;
border-color: #f8bbd9;
}
.success {
color: #388e3c;
background-color: #e8f5e8;
border-color: #c8e6c9;
}
.public-key-section {
margin-bottom: 30px;
padding: 20px;
background-color: #f8f9fa;
border-radius: 5px;
}
.card-form {
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
background-color: #fafafa;
}
.loading {
display: none;
text-align: center;
margin-top: 10px;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<h1>Card Encryption</h1>
<!-- Public Key Input Section -->
<div class="public-key-section">
<div class="form-group">
<label for="publicKey">RSA Public Key (Base64 PKIX format):</label>
<textarea id="publicKey" rows="8" placeholder="Enter your Base64-encoded RSA public key here..."></textarea>
</div>
</div>
<!-- Card Details Form -->
<div class="card-form">
<h3>Card Holder Details</h3>
<form id="cardForm">
<div class="form-group">
<label for="cardNumber">Card Number:</label>
<input type="text" id="cardNumber" placeholder="1234 5678 9012 3456" maxlength="19" required>
</div>
<div class="form-group">
<label for="cardholderName">Cardholder Name:</label>
<input type="text" id="cardholderName" placeholder="John Doe" required>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label for="expiryMonth">Expiry Month:</label>
<input type="number" id="expiryMonth" min="1" max="12" placeholder="MM" required>
</div>
</div>
<div class="col">
<div class="form-group">
<label for="expiryYear">Expiry Year:</label>
<input type="number" id="expiryYear" min="01" max="99" placeholder="YY" required>
</div>
</div>
</div>
<div class="form-group">
<label for="cvv">CVV:</label>
<input type="text" id="cvv" placeholder="123" maxlength="4">
</div>
<button type="submit" class="btn" id="encryptBtn">Encrypt Card Details</button>
</form>
</div>
<!-- Loading Indicator -->
<div class="loading" id="loadingIndicator">
<div class="spinner"></div>
<p>Encrypting...</p>
</div>
<!-- Result Display -->
<div id="result" class="result" style="display: none;"></div>
</div>
<script>
// Hybrid Encryption Class
class HybridEncryption {
/**
* Encrypts plaintext using hybrid encryption (RSA-OAEP + AES-GCM)
* @param {string} plaintext - The text to encrypt
* @param {string} base64PublicKey - Base64-encoded PKIX/SubjectPublicKeyInfo public key
* @returns {Promise<string>} Base64-encoded encrypted response
*/
static async encryptHybrid(plaintext, base64PublicKey) {
try {
// Decode the base64 public key
const publicKeyBytes = this.base64ToArrayBuffer(base64PublicKey);
// Import the public key
const publicKey = await crypto.subtle.importKey(
'spki', // PKIX/SubjectPublicKeyInfo format
publicKeyBytes,
{ name: 'RSA-OAEP',hash: 'SHA-256' },
false,
['encrypt']
);
// Generate 32-byte AES key
const aesKey = await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 }, true, ['encrypt']
);
// Generate 12-byte nonce for AES-GCM
const nonce = crypto.getRandomValues(new Uint8Array(12));
// Encrypt plaintext with AES-GCM
const plaintextBuffer = new TextEncoder().encode(plaintext);
const ciphertext = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv: nonce }, aesKey, plaintextBuffer
);
// Export AES key as raw bytes
const aesKeyBytes = await crypto.subtle.exportKey('raw', aesKey);
// Encrypt AES key with RSA-OAEP
const encryptedKey = await crypto.subtle.encrypt(
{ name: 'RSA-OAEP' }, publicKey, aesKeyBytes
);
// Create response payload
const payload = {
encryptedKey: this.arrayBufferToBase64(encryptedKey),
nonce: this.arrayBufferToBase64(nonce),
ciphertext: this.arrayBufferToBase64(ciphertext)
};
// Convert to JSON and encode as base64
const jsonString = JSON.stringify(payload);
const jsonBuffer = new TextEncoder().encode(jsonString);
return this.arrayBufferToBase64(jsonBuffer);
} catch (error) {
throw new Error(`Encryption failed: ${error.message}`);
}
}
/**
* Convert base64 string to ArrayBuffer
* @param {string} base64 - Base64 string
* @returns {ArrayBuffer} ArrayBuffer
*/
static base64ToArrayBuffer(base64) {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
/**
* Convert ArrayBuffer to base64 string
* @param {ArrayBuffer} buffer - ArrayBuffer
* @returns {string} Base64 string
*/
static arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
}
// Make it available globally
window.HybridEncryption = HybridEncryption;
// UI Event Handlers
document.addEventListener('DOMContentLoaded', function() {
const cardForm = document.getElementById('cardForm');
const encryptBtn = document.getElementById('encryptBtn');
const loadingIndicator = document.getElementById('loadingIndicator');
const resultDiv = document.getElementById('result');
// Format card number input
document.getElementById('cardNumber').addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
value = value.replace(/(\d{4})(?=\d)/g, '$1 ');
e.target.value = value;
});
// Format CVV input (numbers only)
document.getElementById('cvv').addEventListener('input', function(e) {
e.target.value = e.target.value.replace(/\D/g, '');
});
// Handle form submission
cardForm.addEventListener('submit', async function(e) {
e.preventDefault();
const publicKey = document.getElementById('publicKey').value.trim();
const cardNumber = document.getElementById('cardNumber').value.replace(/\s/g, '');
const cardholderName = document.getElementById('cardholderName').value.trim();
const expiryMonth = document.getElementById('expiryMonth').value;
const expiryYear = document.getElementById('expiryYear').value;
const cvv = document.getElementById('cvv').value;
// Validation
if (!publicKey) {
showResult('Please enter a valid RSA public key.', 'error');
return;
}
if (!cardNumber || cardNumber.length < 13 || cardNumber.length > 19) {
showResult('Please enter a valid card number.', 'error');
return;
}
if (!cardholderName) {
showResult('Please enter the cardholder name.', 'error');
return;
}
if (!expiryMonth || expiryMonth < 1 || expiryMonth > 12) {
showResult('Please enter a valid expiry month (1-12).', 'error');
return;
}
if (!expiryYear || expiryYear < 25) {
showResult('Please enter a valid expiry year.', 'error');
return;
}
// Prepare card data for encryption
const payload = {
card: {
number: cardNumber,
expiryMonth: expiryMonth.padStart(2, '0'),
expiryYear: expiryYear,
cvc: cvv,
nameOnCard: cardholderName,
},
deviceInformations: {
type: "",
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
ipAddress: "254.254.254.254",
acceptLanguage: "EN",
cookieToken: "ZU_0oRV1S3D95Rz06Q1Aa0RTeOlgdXWKeVvZEk7k3LM=",
deviceId: "067783c8-29ac-4684-8aa8-71c05ab346df",
browserWidth: "1234",
browserHeight: "1234",
country: "ID"
},
metadata: {}
};
const plaintextData = JSON.stringify(payload);
// Show loading
showLoading(true);
try {
// Encrypt the card data
const encryptedData = await HybridEncryption.encryptHybrid(plaintextData, publicKey);
showResult(`
<h4>Encryption Successful!</h4>
<p><strong>Encrypted Data:</strong></p>
<textarea readonly style="width: 100%; height: 100px; font-family: monospace; font-size: 12px;">${encryptedData}</textarea>
<p><strong>Original Data:</strong></p>
<pre style="background: #f0f0f0; padding: 10px; border-radius: 3px; font-size: 12px;">${JSON.stringify(payload, null, 2)}</pre>
`, 'success');
} catch (error) {
showResult(`Encryption failed: ${error.message}`, 'error');
} finally {
showLoading(false);
}
});
function showLoading(show) {
loadingIndicator.style.display = show ? 'block' : 'none';
encryptBtn.disabled = show;
}
function showResult(message, type) {
resultDiv.innerHTML = message;
resultDiv.className = `result ${type}`;
resultDiv.style.display = 'block';
resultDiv.scrollIntoView({ behavior: 'smooth' });
}
});
</script>
</body>
</html>
Last updated