使用Java实现价格加密与优化功能
作者:码农阿豪@新空间代码工作室
引言
在现代软件开发中,数据加密是一个非常重要的环节,尤其是在处理敏感信息(如价格、用户数据等)时。本文将详细介绍如何使用 Java 实现价格加密,并对代码进行优化,以提高其健壮性、可维护性和性能。
1. 背景
在广告交易系统中,价格信息通常需要加密以确保其安全性。Google 的 DoubleClick Ad Exchange 提供了一种加密方案,使用 HMAC-SHA1 算法对价格进行加密。本文将基于这一方案,实现一个价格加密工具,并逐步优化代码。
2. 实现价格加密
2.1 加密原理
DoubleClick 的加密方案使用两个密钥:
- 加密密钥(Encryption Key):用于加密价格数据。
- 完整性密钥(Integrity Key):用于生成签名,确保数据的完整性。
加密后的数据格式如下:
initVector:16 || E(payload:?) || I(signature:4)
其中:
initVector
是初始化向量,包含时间戳和服务器 ID。E(payload)
是加密后的价格数据。I(signature)
是完整性签名。
2.2 基础实现
以下是基础的价格加密实现:
import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class PriceEncryptor { private static final String HMAC_ALGORITHM = "HmacSHA1"; /** * 加密价格 * * @param winPrice 价格字符串 * @param enKey 加密密钥(Base64 编码) * @param ivKey 完整性密钥(Base64 编码) * @return 加密后的价格字符串(Base64 编码) * @throws IllegalArgumentException 如果参数无效 * @throws RuntimeException 如果加密失败 */ public static String priceEncrypt(String winPrice, String enKey, String ivKey) { // 参数校验 Objects.requireNonNull(winPrice, "价格不能为空"); Objects.requireNonNull(enKey, "加密密钥不能为空"); Objects.requireNonNull(ivKey, "完整性密钥不能为空"); if (winPrice.trim().isEmpty()) { throw new IllegalArgumentException("价格不能为空字符串"); } try { // 将价格转换为 double double priceValue = Double.parseDouble(winPrice); // 解析密钥 SecretKey encryptionKey = decodeBase64ToSecretKey(enKey, HMAC_ALGORITHM); SecretKey integrityKey = decodeBase64ToSecretKey(ivKey, HMAC_ALGORITHM); // 创建加密工具 DoubleClickCrypto.Keys keys = new DoubleClickCrypto.Keys(encryptionKey, integrityKey); DoubleClickCrypto.Price crypto = new DoubleClickCrypto.Price(keys); // 加密价格 return crypto.encodePriceValue(priceValue, null); } catch (NumberFormatException e) { throw new IllegalArgumentException("价格格式无效: " + winPrice, e); } catch (Exception e) { throw new RuntimeException("加密失败", e); } } /** * 将 Base64 编码的密钥转换为 SecretKey * * @param base64Key Base64 编码的密钥 * @param algorithm 密钥算法 * @return SecretKey * @throws IllegalArgumentException 如果密钥无效 */ private static SecretKey decodeBase64ToSecretKey(String base64Key, String algorithm) { try { byte[] keyBytes = Base64.getDecoder().decode(base64Key); return new SecretKeySpec(keyBytes, algorithm); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("无效的 Base64 密钥: " + base64Key, e); } } public static void main(String[] args) { try { String bidPrice = priceEncrypt("88", "your_base64_encoded_enKey", "your_base64_encoded_ivKey"); System.out.println("加密后价格:" + bidPrice); } catch (Exception e) { System.err.println("加密失败: " + e.getMessage()); e.printStackTrace(); } } }
2.3 代码说明
参数校验:
- 使用
Objects.requireNonNull
检查winPrice
、enKey
和ivKey
是否为null
。 - 检查
winPrice
是否为空字符串。
- 使用
异常处理:
- 捕获
NumberFormatException
,提供清晰的错误信息。 - 捕获其他异常,统一抛出
RuntimeException
。
- 捕获
密钥解析:
- 将 Base64 编码的密钥转换为
SecretKey
。
- 将 Base64 编码的密钥转换为
加密逻辑:
- 使用
DoubleClickCrypto.Price
对价格进行加密。
- 使用
3. 优化代码
3.1 参数校验
在加密方法中,参数校验是必不可少的。我们使用 Objects.requireNonNull
来确保参数不为 null
,并检查价格字符串是否为空。
Objects.requireNonNull(winPrice, "价格不能为空"); Objects.requireNonNull(enKey, "加密密钥不能为空"); Objects.requireNonNull(ivKey, "完整性密钥不能为空"); if (winPrice.trim().isEmpty()) { throw new IllegalArgumentException("价格不能为空字符串"); }
3.2 异常处理
为了提供更好的错误信息,我们捕获 NumberFormatException
并抛出 IllegalArgumentException
。其他异常则统一抛出 RuntimeException
。
try { double priceValue = Double.parseDouble(winPrice); // ... } catch (NumberFormatException e) { throw new IllegalArgumentException("价格格式无效: " + winPrice, e); } catch (Exception e) { throw new RuntimeException("加密失败", e); }
3.3 代码复用
将密钥解析逻辑封装到 decodeBase64ToSecretKey
方法中,避免重复代码。
private static SecretKey decodeBase64ToSecretKey(String base64Key, String algorithm) { try { byte[] keyBytes = Base64.getDecoder().decode(base64Key); return new SecretKeySpec(keyBytes, algorithm); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("无效的 Base64 密钥: " + base64Key, e); } }
3.4 性能优化
如果 priceEncrypt
方法会被频繁调用,可以考虑将 DoubleClickCrypto.Keys
和 DoubleClickCrypto.Price
的实例缓存起来,避免重复创建。
private static final Map<String, DoubleClickCrypto.Price> CRYPTO_CACHE = new ConcurrentHashMap<>(); private static DoubleClickCrypto.Price getCrypto(String enKey, String ivKey) { String cacheKey = enKey + "|" + ivKey; return CRYPTO_CACHE.computeIfAbsent(cacheKey, k -> { SecretKey encryptionKey = decodeBase64ToSecretKey(enKey, HMAC_ALGORITHM); SecretKey integrityKey = decodeBase64ToSecretKey(ivKey, HMAC_ALGORITHM); DoubleClickCrypto.Keys keys = new DoubleClickCrypto.Keys(encryptionKey, integrityKey); return new DoubleClickCrypto.Price(keys); }); }
然后在 priceEncrypt
方法中使用 getCrypto
获取 DoubleClickCrypto.Price
实例。
DoubleClickCrypto.Price crypto = getCrypto(enKey, ivKey); return crypto.encodePriceValue(priceValue, null);
4. 总结
通过以上步骤,我们实现了一个健壮、高效的价格加密工具。优化后的代码具有以下优点:
- 健壮性:通过参数校验和异常处理,确保代码在异常情况下也能正常运行。
- 可维护性:通过代码复用和模块化设计,提高了代码的可读性和可维护性。
- 性能:通过缓存加密工具实例,减少了重复创建对象的开销。
到此这篇关于使用Java实现价格加密与优化功能的文章就介绍到这了,更多相关Java价格加密与优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!