赞
踩
和第三方系统对接时,需要对隐私数据进行加密,对请求报文进行签名等。加密算法分为单向加密、对称加密、非对称加密等,其对应的算法也各式各样。Java 提供了统一的框架(java.security.*)来规范安全加密。下面将一一介绍以下内容。
一、加密算法概念及分类
常用的加密算法类型有三种,如下:
二、密钥生成
2.1 对称密钥生成
KeyGenerator 中的几个重要的方法如下。
- public static final KeyGenerator getInstance(String algorithm, String provider)
- public static final KeyGenerator getInstance(String algorithm)
- public final void init(int keysize)
- public final void init(int keysize, SecureRandom random)
- public final void init(SecureRandom random)
- public final void init(AlgorithmParameterSpec params, SecureRandom random)
- public final SecretKey generateKey()
-
示例:
- public static void main(String[] args) throws Exception {
- KeyGenerator kg = KeyGenerator.getInstance("DES");
- SecureRandom random = new SecureRandom();
- random.nextBytes(new byte[128]);
- kg.init(56, random);
- SecretKey sk = kg.generateKey();
- byte[] b = sk.getEncoded();
- System.out.println(new String(Base64.encodeBase64(b))); // XZdrC/in5uk=
- }
-
2.2 非对称密钥生成
KeyPairGenerator.java 和 KeyPair.java 类中的重要的方法如下所示。
- // KeyPairGenerator.java
- public static KeyPairGenerator getInstance(String algorithm)
- public static KeyPairGenerator getInstance(String algorithm, String provider)
- public void initialize(int keysize, SecureRandom random)
- public void initialize(AlgorithmParameterSpec params, SecureRandom random)
- public final KeyPair genKeyPair()
- // KeyPair.java
- public PublicKey getPublic()
- public PrivateKey getPrivate()
-
示例:
- public static void main(String[] args) throws Exception {
- KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
- SecureRandom random = new SecureRandom();
- random.nextBytes(new byte[516]);
- keyGen.initialize(516, random);
- KeyPair keyPair = keyGen.genKeyPair();
- PublicKey publicKey = keyPair.getPublic();
- PrivateKey privateKey = keyPair.getPrivate();
- byte[] publicKeyEncoded = publicKey.getEncoded();
- byte[] privateKeyEncoded = privateKey.getEncoded();
- System.out.println(new String(Base64.encodeBase64(publicKeyEncoded)));
- // MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBCJQ3Ee/oxid0CkYxQaNyUlPlIJKFUuwB+kYAuZ5OdxJjSRHJ7jb931aIU+t61DhG2BBiegs3588SyGRe8IQZM10CAwEAAQ==
- System.out.println(new String(Base64.encodeBase64(privateKeyEncoded)));
- // MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEIlDcR7+jGJ3QKRjFBo3JSU+UgkoVS7AH6RgC5nk53EmNJEcnuNv3fVohT63rUOEbYEGJ6CzfnzxLIZF7whBkzXQIDAQABAkEFjPhQp7whMXe4ChBmmr0mHVf7ijGvJDpnVxGzB4VXL0+5TGT0fptb85dNjVmKD2REe0fBntRh7hSZETgYCiZMgQIhAwPbBuZ3QjDhMfx3fb89xCnLZFzEILzvKXeS1Q5xx/ehAiEC2Go0R13hndaDIzhq/Rn2fsVLzAlAFXIJBEdTVZ498j0CIQKYbA/JjjmVWBUubjH50RKuo54WWOKRoRLCEsyCraFkYQIgS4MnDEb1PrGgQqR0ouxwG1BEvVAwLoj12lWyk+ulrFkCIQJyg5t1WkvLVeqrGOGhj5jIkWEfxad/43X2fkFM6WyL3Q==
- }
-

2.3 密钥 Key 和密钥规格 KeySpec 的相互转化
KeySpec 是一个接口,用来组成密钥内容的规范。如果密钥存储在硬件设备上,则其规范可以包含有助于标识该设备上的密钥的信息。
KeySpec 具有规范性,所以一般会根据外部参数生成 KeySpec,再根据 KeySpec 生成对应的 Key。SecretKeyFactory、KeyFactory 的作用就是转换 Key 与 KeySpec。
SecretKeyFactory 用于对称加密的密钥和密钥规格之间的转换,配合 KeyGenerator 使用,支持算法:AES、ARCFOUR、DES、DESede、PBEWithMD5AndDES、PBEWithHmacSHA256AndAES_128、PBKDF2WithHmacSHA256 等。
SecretKeyFactory.java 中的几个方法如下所示。
- public static final SecretKeyFactory getInstance(String algorithm)
- public static final SecretKeyFactory getInstance(String algorithm, String provider)
- public final SecretKey translateKey(SecretKey key)
- public final SecretKey generateSecret(KeySpec keySpec)
- public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)
-
代码示例:
- public static void main(String[] args) throws Exception {
- SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
- byte[] desKey = "hello world".getBytes(StandardCharsets.UTF_8); // 设置密钥
- DESKeySpec keySpec = new DESKeySpec(desKey); // 设置密钥参数
- SecretKey key = keyFactory.generateSecret(keySpec); // 得到密钥对象
- byte[] b = key.getEncoded();
- System.out.println(new String(Base64.encodeBase64(b))); // aGRtbW5XV1c=
- }
-
KeyFactory 用于非对称加密的密钥和密钥规格之间的转换,配合 KeyPairGenerator 使用,支持算法:DiffieHellman、DSA、RSA、RSASSA-PSS、EC 等。
KeyFactory.java 中的几个方法如下所示。
- // KeyFactory.java
- public static KeyFactory getInstance(String algorithm)
- public static KeyFactory getInstance(String algorithm, String provider)
- public final PublicKey generatePublic(KeySpec keySpec)
- public final PrivateKey generatePrivate(KeySpec keySpec)
- public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
-
代码示例:
- public static void main(String[] args) throws Exception {
- // 生成 RSA 密钥对
- KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
- SecureRandom random = new SecureRandom();
- random.nextBytes(new byte[2048]);
- keyGen.initialize(2048, random);
- KeyPair keyPair = keyGen.genKeyPair();
-
- // PublicKey 转 KeySpec; KeySpec 再转 PublicKey
- X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
- byte[] pubKeyEncoded = pubKey.getEncoded();
- System.out.println(new String(Base64.encodeBase64(pubKeyEncoded)));
- // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAglncEo1/cWWMQzPxShtZY+zMERNcI6EHgEtYcPJaxF0mLVKk0af/5YB1WMHkEiq/CaRJa1GPS24iATIZpl3ICSqo8gSbgctogOxCU+XBtWhyVBgnaPpt4xoNFpoGyNyZzOvEq4YiNVDMhnTD+0Qlx7jyvV8R3xWcGWyZHB68KGwj9NvxHcsxkDZzXqAkDdiqdmqlImQoS9NBdRWQarX/rcBooQ9qs3yxu8i/bufVwwQS+lPvZoaKzJOvA4/qraa+ffXPJjsyLZk67C6ckQjmRbhgGuoa6fJ7FCRc98qZy9Cx/NxiqypHkIG0glgoOA4u1RIHBOEWY4Vo3G0d0Tw5PwIDAQAB
-
- // PrivateKey 转 KeySpec; KeySpec 再转 PrivateKey
- PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(keyPair.getPrivate().getEncoded());
- PrivateKey priKey = keyFactory.generatePrivate(priKeySpec);
- byte[] priKeyEncoded = priKey.getEncoded();
- System.out.println(new String(Base64.encodeBase64(priKeyEncoded)));
- // MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQCCWdwSjX9xZYxDM/FKG1lj7MwRE1wjoQeAS1hw8lrEXSYtUqTRp//lgHVYweQSKr8JpElrUY9LbiIBMhmmXcgJKqjyBJuBy2iA7EJT5cG1aHJUGCdo+m3jGg0WmgbI3JnM68SrhiI1UMyGdMP7RCXHuPK9XxHfFZwZbJkcHrwobCP02/EdyzGQNnNeoCQN2Kp2aqUiZChL00F1FZBqtf+twGihD2qzfLG7yL9u59XDBBL6U+9mhorMk68Dj+qtpr599c8mOzItmTrsLpyRCOZFuGAa6hrp8nsUJFz3ypnL0LH83GKrKkeQgbSCWCg4Di7VEgcE4RZjhWjcbR3RPDk/AgMBAAECggEBAIB/TsfnPvOtNEjnQnxYW5V60Gwg1pq02i0pmUS2VK3wWXsiViHraAJ40LUvZcJW6z34+vtVSloEdncRSWHMXy5SJHt3+UhJGXrF7FjCTGOlU9b8fJUrEfpnKvHV4sxNUzxESvr/XmeKgCQnpS7kLg4ljv0JZBezOM+DU6f50GhTSWJeTGzCOfGl6xXjpLeeYnnbEtCKG5qo3YH3wAeFF0Zvb6Rqm0pXJwQ/YMUNFG/2CoAktKtUfpF6DSbmFzzRA03nWqRrGaWVqtzCmQ7ndSWsdeG00RjNRkA94VevoHZV9G3rLgzPmfWF5nn1QT/SGAUAU+VmgoG0dcmDyivN91ECgYEA48zUx3Mw09NCl9TAofHFFAY6TdR/7dmThzTsEzJoCzyjvLOEUExMI8w6W2t5d4jYx3hxgQoK8mbZfn9vWrK9IEZEsQ25ec/6kqW+hpcwXTaN5aTWRUILJTz5yHothaEbK5sDSRTRFvEVlxszikmJfT6Z1/4rQr0mw+a4ZuOp61kCgYEAknzJunQYfLOvSnJocX9ms5sFkA+wFq9twHXptUTeh2wcxz0C2zRobsrlrW8CwWG5q9P90ywRXCaoM3fp5w+x8qPLmdzW/GNQC/F5o+d/SnNYMSdPr4OS14I3gu8zMO9eTWnLY8IYoxeXRl0/5/ewtM8WvsW/KrXErYjqf9elblcCfwHHl+H3BGqjO+Hzx418Vg3R/qKdBmLVUFG+GBoOSsHLt3vB60a1UeL1tX8BV/GXIBpu1nQrn+pE424ZkMUkoFWgNukrMkfBWDPNF6/1fms8Ad/JaeMgoPWphEoMqk5g89VjYKMxhnCncYO8sqph6LERzCHj2nKrB6KAKvCi1rECgYABCqYcj0rFSDnM27dmZzOBv25wscvcvW6YWb5Jra2vZNNnj0V/7YV4lDTB4PIyEdHSKPW7FKsi7ptvkkC1heUMBqIh+/IDZWliTFtDERhUnTFZWCA27UaUBbcDVVQV2v3eqwvpL64hKr/Gnk8gBSDaiEZvINTVJum5GiogspXYjQKBgAV2DXc2P4AHqt981ou3GPtFsAfcL3JjwslnIkgNk7nEReSTmsJ2rERrLUKQEIKLNdxBOrK/0AgsK8+ysFk/+lmVd9rGY3kROF4HRvV8aIoLGkKlpIjhNhTpmlWzfFrMXebtiK2iEfbZcC1wedl+V00Q9YntOYMlJPdfhl1wxN7H
- }
-

三、摘要算法 - MessageDigest 和 javax.crypto.Mac(HMAC)
- public static void main(String[] args) throws Exception {
- MessageDigest digest = MessageDigest.getInstance("MD5");
- System.out.println(new String(Base64.encodeBase64(digest.digest("hello world!".getBytes()))));
- // /D/5joxqDTCH1RXARz+Gdw==
- System.out.println(new String(Base64.encodeBase64(digest.digest("hello happy!".getBytes()))));
- // mfzFDfIxtbUOJRN7WGSNVA==
- }
-
- public static void main(String[] args) throws Exception {
- // 初始化 HmacMD5 摘要算法的密钥产生器
- KeyGenerator generator = KeyGenerator.getInstance("HmacMD5");
- // 产生密钥
- SecretKey secretKey = generator.generateKey();
- // SecretKeySpec 继承于 SecretKey 和 KeySpec,因此可直接用 SecretKeySpec 初始化 Mac
- // SecretKey secretKey = new SecretKeySpec("password".getBytes(), "HmacMD5");
- Mac mac = Mac.getInstance("HmacMD5");
- mac.init(secretKey);
- // 计算摘要
- String data = "hello world";
- byte[] result1 = mac.doFinal(data.getBytes());
- System.out.println(new String(Base64.encodeBase64(result1)));
- }
-
四、签名算法工具 - Signature
签名后的数据具有唯一标识性,就像一个人的签名能代表一个人的身份。签名一般是指用非对称加密算法的私钥来加密明文的过程,生成的密文可以被持有公钥的人识别解密,只要你的公钥是准确无误的,就能保证你解密的数据是来自持有私钥的一方。
如何保证公钥是正确无误,没被篡改的?
支持算法:NONEwithRSA、MD2withRSA、MD5withRSA、SHA512/224withRSA、SHA512/256withRSA、RSASSA-PSS、NONEwithDSA、SHA512withDSA、NONEwithECDSA、SHA512withECDSA、MD5withRSAandMGF1(太多了,此处选择性列举几个)
Signature 配合 KeyPairGenerator 使用,进行数据签名和验签的 demo 如下所示。
- public static void main(String[] args) throws Exception {
- // 生成 RSA 密钥对
- KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
- SecureRandom random = new SecureRandom();
- random.nextBytes(new byte[1024]);
- keyGen.initialize(1024, random);
- KeyPair keyPair = keyGen.genKeyPair();
-
- Signature signature = Signature.getInstance("MD5withRSA");
- signature.initSign(keyPair.getPrivate());
- // 待签名字符串
- String content = "hello world";
- byte[] data = content.getBytes("UTF-8");
- // 数据签名
- signature.update(data);
- byte[] digest = signature.sign();
- Base64.Encoder encoder = Base64.getEncoder();
- System.out.println("签名后的字符串:" + encoder.encodeToString(digest));
-
- // 数据验签
- signature.initVerify(keyPair.getPublic());
- signature.update(data);
- System.out.println("验签结果:" + signature.verify(digest));
- }
-

五、常用加密工具类 - Cipher
用于加密/解密数据。支持各种类型的算法:对称加密(例如 AES),非对称加密(例如RSA)。
支持算法:AES、AESWrap、ARCFOUR、Blowfish、DES、DESede、DESedeWrap、ECIES、RSA(太多了,选择性列举几个)。
示例见:RSA 加解密(Java 实现)
六、Certificate - 证书存储
示例如下。
- import java.io.InputStream;
- import java.security.cert.CertificateFactory;
-
- // certificateStream 是证书的输入流
- public static PublicKey getPublicKeyByCer(InputStream certificateStream) throws Exception {
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
- Certificate certificate = (Certificate) certificateFactory.generateCertificate(certificateStream);
- return certificate.getPublicKey();
- }
-
七、KeyStore - 密钥证书的实体类
八、java.https 加载证书的 API
KeyManagerFactory、TrustManagerFactory => KeyManager、TrustManager => SSLContext => SSLEngine、SSLSocketFactory、SSLSocket
一般的证书加载过程:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。