How Payment Platforms Secure Data: From DES to TLS and RSA
This article explains the security architecture of payment platforms, covering terminal data protection, symmetric and asymmetric encryption methods such as DES, 3DES, AES, and RSA, code implementations for Android, TLS transmission security, anti‑tampering signatures, and practical key‑management strategies.
Terminal Security Overview
After Ant Group announced its upcoming IPO, JD Digits also prepared for listing, highlighting the rapid growth of third‑party and mobile payments. Secure transaction processing is a core requirement for e‑commerce, and the payment system’s security is the key to safe trading.
Third‑party payment providers must protect terminal data using encryption, access control, and secure transmission.
Symmetric Encryption
Two main symmetric algorithms are used for local data storage: DES (Data Encryption Standard) and AES (Advanced Encryption Standard). DES uses a short 56‑bit key and is vulnerable to brute‑force attacks, while AES provides stronger security and better performance.
Typical usage in Android (Java) includes:
public static String encryptByDES(String plain, String encryKey) throws Exception {
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
DESKeySpec desKeySpec = new DESKeySpec(encryKey.getBytes("UTF-8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(encryKey.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
return new String(Base64.encode(cipher.doFinal(plain.getBytes("UTF-8"))));
} public static String decryptByDES(String encryString, String decodeKey) throws Exception {
IvParameterSpec iv = new IvParameterSpec(decodeKey.getBytes());
SecretKeySpec skeySpec = new SecretKeySpec(decodeKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] byteMi = Base64.decode(decodeString.toCharArray());
byte[] decryptedData = cipher.doFinal(byteMi);
return new String(decryptedData);
}For higher security, 3DES (Triple DES) can be used:
public static String encryptBy3DES(String plain, String secretKey) throws Exception {
DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
SecretKey deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
byte[] encryptData = cipher.doFinal(plain.getBytes("UTF-8"));
return Base64.encodeToString(encryptData, Base64.DEFAULT);
} public static String decryptBy3DES(String encryString, String secretKey) throws Exception {
DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
SecretKey deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
return new String(cipher.doFinal(Base64.decode(encryString, Base64.DEFAULT)));
}AES encryption in Android is similar but uses "AES/ECB/PKCS5Padding" and offers better performance:
public static String encryptByAES(String plain, String secretKey) {
try {
SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, spec);
byte[] crypted = cipher.doFinal(plain.getBytes());
return new String(Base64.encode(crypted, Base64.NO_WRAP));
} catch (Exception e) {
return "";
}
} public static String decryptByAES(String encryString, String secretKey) {
try {
SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, spec);
byte[] output = cipher.doFinal(Base64.decode(encryString, Base64.NO_WRAP));
return new String(output);
} catch (Exception e) {
return "";
}
}Asymmetric Encryption (RSA)
RSA uses a public‑private key pair. The public key encrypts data, and the private key decrypts it. Key generation can be done with OpenSSL or Java APIs.
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); public static byte[] encryptByPubKey(byte[] plain, byte[] publicKey) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Cipher cp = Cipher.getInstance("RSA/None/PKCS1Padding");
cp.init(Cipher.ENCRYPT_MODE, pubKey);
return cp.doFinal(plain);
} public static byte[] decryptByPrivKey(byte[] encrypted, byte[] privateKey) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey keyPrivate = kf.generatePrivate(keySpec);
Cipher cp = Cipher.getInstance("RSA/None/PKCS1Padding");
cp.init(Cipher.DECRYPT_MODE, keyPrivate);
return cp.doFinal(encrypted);
}Transmission Security (TLS)
TLS (Transport Layer Security) protects data in transit. An Android implementation loads a trusted X.509 certificate, creates a TrustManager, and initializes an SSLContext:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new ByteArrayInputStream(caPath.getBytes()));
Certificate ca = cf.generateCertificate(caInput);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("ca", ca);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);After creating a socket from the context, the client connects and starts the TLS handshake.
SocketAddress sockaddr = new InetSocketAddress("localhost", 80);
Socket socket = context.getSocketFactory().createSocket();
socket.connect(sockaddr, 60 * 1000);
socket.startHandshake();Anti‑Tampering and Signing
To prevent data tampering, the client signs the request parameters. The process includes sorting parameters, trimming whitespace, concatenating them as "key=value" pairs, generating a digest (e.g., MD5), and encrypting the digest with the client’s RSA public key. The server verifies the signature by decrypting with the corresponding private key and comparing digests.
String param = param.replaceFirst("&", "");
String signValue = Md5Utils.md5(param);
String signedParam = param + "&sign=" + signValue;The same steps—parameter ordering, digest generation, RSA decryption, and comparison—are performed on the server side to ensure integrity.
Reference
The technical content is excerpted from the book 《支付平台架构:业务、规划、设计与实现》 , which provides detailed design and implementation guidance for payment platforms.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
