赠书:支付平台架构业务、规划、设计与实现
点击上方蓝色“程序猿DD”,选择“设为星标”
回复“资源”获取独家整理的学习资料!
前蚂蚁集团宣布即将IPO之后,9月11日晚间,以金融支付起家的京东数科也要上市了。近年来,第三方支付业务的资金规模不断扩大,支付业务量稳步增长,“第三方支付”及“移动支付”已成为年度搜索热词,支付平台作为互联网产品及其在商业化过程中信息流和资金流的支撑,也成为国外内各大互联网公司必建的基础平台之一。
终端安全技术实现
一、中低安全级别的数据(DES)
数据加密标准DES(Data Encryption Standard)是使用对称密钥加密的一种块加密算法,处理数据的速度较快,性能较好,通常适用于对大块数据加解密的场景中。
该算法的明显缺点是密钥较短,这意味着可以通过暴力破解来解密,降低了加密的安全性,但仍然适用于对支付系统配置文件的安全加密等场景中。
1/**
2 * 采用DES加密字符串数据,使用UTF-8编码
3 * @param plain原字符串
4 * @param encryKey密钥
5 * @return密文
6 * @throws Exception
7 */
8 public static String encryptByDES(String plain, String encryKey)
9 throws Exception {
10 //获取密码实例对象,参数格式为"算法/模式/填充"
11 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
12 //使用Key作为DES密钥的密钥内容,创建一个 DESKeySpec对象
13 DESKeySpec desKeySpec = new DESKeySpec(encryKey.getBytes("UTF-8"));
14 //返回DES算法的SecretKeyFactory对象
15 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
16 //生成SecretKey对象
17 SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
18 //使用密钥构造一个IvParameterSpec对象。
19 IvParameterSpec iv = new IvParameterSpec(encryKey.getBytes());
20 //用密钥和一组算法参数初始化密码实例对象
21 cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
22 //加密,使用Base64密码
23 return new String(Base64.encode(cipher.doFinal(plain
24 .getBytes("UTF-8"))));
25 }
1 /**
2 * 使用密码和密钥解密数据
3 * @param encryString密文
4 * @param decodeKey密钥
5 * @return明文
6 * @throws Exception
7 */
8 public static String decryptByDES(String encryString, String decodeKey) throws Exception {
9 //使用密钥构造IV对象
10 IvParameterSpec iv = new IvParameterSpec(decodeKey.getBytes());
11 //根据密钥和DES算法构造一个SecretKeySpec
12 SecretKeySpec skeySpec = new SecretKeySpec(decodeKey.getBytes(), "DES");
13 //返回实现了指定转换的Cipher对象
14 Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
15 //解密初始化
16 cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
17 //解码返回
18 byte[] byteMi = Base64.decode(decodeString.toCharArray());
19 byte decryptedData[] = cipher.doFinal(byteMi);
20 return new String(decryptedData);
21 }
二、DES算法演进之3DES
1/**
2 * 采用3DES加密字符串
3 *
4 * @param plain
5 * 普通文本
6 * @return
7 * @throws Exception
8 */
9 public static String encryptBy3DES(String plain, String secretKey) throws Exception {
10 Key deskey = null ;
11 DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
12 //根据3DES构造一个SecretKeyFactory
13 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "desede");
14 deskey = keyfactory.generateSecret(spec);
15
16 //获取密码实例对象,参数格式为"算法/模式/填充"
17 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
18 IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
19 cipher.init(Cipher. ENCRYPT_MODE , deskey, ips);
20 byte [] encryptData = cipher.doFinal(plain.getBytes("UTF-8"));
21 return Base64.encodeToString(encryptData,Base64.DEFAULT);
22 }
解密函数示例如下:
1/**
2 * 3DES解密
3 * @param encryString密文
4 * @return明文
5 * @throws Exception
6 */
7 public static String decryptBy3DES(String encryString, String secretKey) throws Exception {
8 Key deskey = null ;
9 DESedeKeySpec spec = new DESedeKeySpec( secretKey.getBytes());
10 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "desede" );
其中三重数据加密算法的密钥长度是128位。除了3DES算法,还有人演算出N-DES(N重数据加密算法)。
高安全级别的数据(AES)
1/**
2 * AES加密
3 * @param plain明文
4 * @return密文
5 * @throws Exception
6 */
7 public static String encryptByAES(String plain, String secretKey){
8 byte[] crypted = null;
9 try{
10 SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
11 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
12 cipher.init(Cipher.ENCRYPT_MODE, spec);
13 crypted = cipher.doFinal(plain.getBytes());
14 }catch(Exception e){
15 return "";
16 }
17 return new String(Base64.encode(crypted, Base64.NO_WRAP));
18 }
1/**
2 * AES解密
3 * @param encryString密文
4 * @return明文
5 * @throws Exception
6 */
7 public static String decryptByAES(String encryString, String secretKey){
8 byte[] output = null;
9 try{
10 SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");
11 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
12 cipher.init(Cipher.DECRYPT_MODE, spec);
13 output = cipher.doFinal(Base64.decode(encryString, Base64.NO_WRAP));
14 } catch(Exception e){
15 return "";
16 }
17 return new String(output);
18 }
非对称加密(RSA)
RSA是一种非对称加密算法,由三位数学家Rivest、Shamir和Adleman设计,其核心思想为将密钥分成以下两把密钥,简称密钥对。
公钥(Public Key)
是密钥对中完全公开的部分,任何人都可以得到它,适用于客户端-服务端模型。
私钥(Private Key)
是密钥对中保密的一部分,一般在服务端安全存储,不允许在客户端存储。
注意 ——
可以使用Java代码从rsa_private_key_pkcs8.pem文件中读取私钥信息并生成数字签名,再使用rsa_public_key.pem公钥文件验证数字签名的正确性。
1/**
2 * 生成非对称密钥对
3 * @throws NoSuchAlgorithmException
4 */
5 public static void genKeyPair() throws NoSuchAlgorithmException {
6 //KeyPairGenerator类,基于RSA算法生成对象
7 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
8 //初始化密钥对生成器
9 keyPairGen.initialize(1024,new SecureRandom());
10 //生成一个密钥对,保存在keyPair对象中
11 KeyPair keyPair = keyPairGen.generateKeyPair();
12 //得到私钥对象
13 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
14 //得到公钥对象
15 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
16
17 //公钥字符串
18 String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
19 //私钥字符串
20 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
21 }
1/**
2 * 使用公钥进行加密
3 * @param plain明文数据
4 * @param publicKey公钥数据
5 * @return密文
6 * @throws Exception
7 */
8 public static byte[] encryptByPubKey(byte[] plain, byte[] publicKey) throws Exception {
9 //从公钥数据中得到KeySpec对象
10 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
11 //根据RSA算法构造一个KeyFactory
12 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
13 PublicKey pubKey = keyFactory.generatePublic(keySpec);
14 //获取密码实例对象 参数格式为"算法/模式/填充"
15 Cipher cp = Cipher.getInstance("RSA/None/PKCS1Padding");
16 cp.init(Cipher.ENCRYPT_MODE, pubKey);
17 return cp.doFinal(plain);
18 }
1/**
2 * 使用私钥解密
3 * @param encrypted
4 * @param privateKey
5 * @return
6 * @throws Exception
7 */
8 public static byte[] decryptByPrivKey(byte[] encrypted, byte[] privateKey) throws Exception {
9 //从私钥数据中得到KeySpec对象
10 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
11 KeyFactory kf = KeyFactory.getInstance("RSA");
12 PrivateKey keyPrivate = kf.generatePrivate(keySpec);
13 //获取密码实例对象,参数格式为"算法/模式/填充"
14 Cipher cp = Cipher.getInstance("RSA/None/PKCS1Padding");
15 cp.init(Cipher.DECRYPT_MODE, keyPrivate);
16 byte[] arr = cp.doFinal(encrypted);
17 return arr;
18 }
传输安全
▊1、防窥探
(例如:现在常用的网络数据抓包软件就有Fiddler、Wireshark等,可以监听到网络层都采用了什么协议、调用了哪些API,以及发送参数、返回的响应数据分别是什么。)
1//用keytool将.keystore中的证书写入文件中,然后从该文件中读取证书信息
2CertificateFactory cf = CertificateFactory.getInstance("X.509");
3InputStream caInput = new BufferedInputStream(new ByteArrayInputStream(caPath.getBytes()));
4Certificate ca;
5try {
6 ca = cf.generateCertificate(caInput);
7} finally {
8 caInput.close();
9}
10
11//创建一个包含认证证书的KeyStore
12String keyStoreType = KeyStore.getDefaultType();
13KeyStore keyStore = KeyStore.getInstance(keyStoreType);
14keyStore.load(null, null);
15keyStore.setCertificateEntry("ca", ca);
16
17//创建一个基于KeyStore算法的TrustManager对象
18String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
19TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
20tmf.init(keyStore);
21
22//初始化TLS
23SSLContext context = SSLContext.getInstance("TLS");
24context.init(null, tmf.getTrustManagers(), null);
1//远程服务器的地址
2SocketAddress sockaddr = new InetSocketAddress("localhost", 80);
3//创建Socket对象实例
4Socket socket = context.getSocketFactory().createSocket();
5//开始连接
6socket.connect(sockaddr, 60 * 1000);
7//开始TLS握手
8socket.startHandshake();
▊ 2、防篡改
1 /**
2 * 对参数字段进行排序
3 * @param params参数数据
4 * @return
5 */
6 public String orderByParameters(Map<String, String> params) {
7 StringBuilder sb = new StringBuilder();
8 //以参数名称的字典进行升序排列
9 Map<String, String> sortParams = new TreeMap<String, String>(params);
10 //拼接成"key=value"格式
11 for (Map.Entry<String, String> entry : sortParams.entrySet()) {
12 String key = entry.getKey();
13 //字符串去空格
14 String value = entry.getValue().trim();
15 key = key.trim();
16 if (TextUtils.isEmpty(value))
17 sb.append("&").append(key).append("=").append(value);
18 }
19 return sb.toString();
20 }
1//替换第1个间隔符号
2String param = param.replaceFirst("&","");
3//生成摘要数据
4String signValue = Md5Utils.md5(param);
5//拼接摘要数据
6String param = param + "&sign=" + signValue;
相关图书
《支付平台架构:业务、规划、设计与实现》
曹兵强 著
移动支付虽已普及,但其高门槛另使绝大多数技术人员没机会深入了解支付平台的架构和设计技巧。
《支付平台架构:业务、规划、设计与实现》一书梳理支付平台的各个业务和技术细节,讲解支付架构原理和技术实现。既有支付领域端到端的全链路设计思路,也有关键技术方案的实现细节和经验总结。是一本国内少见且非常具有参考价值的好书。
▊作者简介
截止时间:2020年10月18日 11:30
如何抽奖:扫描下方二维码,关注公众号,回复关键词 :抽奖