/* * Copyright 2015 Rocko (http://rocko.xyz) <rocko.zxp@gmail.com>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package xyz.rocko.security.security.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import xyz.rocko.security.util.Base64Utils; /** * @author Mr.Zheng * @date 2014年8月22日 下午1:44:23 */ public final class RSAUtils { private final static String KEY_PAIR = "RSA"; private final static String CIPHER = "RSA/ECB/PKCS1Padding"; /** * 随机生成RSA密钥对(默认密钥长度为1024) * * @return */ public static KeyPair generateRSAKeyPair() { return generateRSAKeyPair(1024); } /** * 随机生成RSA密钥对 * * @param keyLength * 密钥长度,范围:512~2048<br> * 一般1024 * @return */ public static KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_PAIR); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } /** * 用公钥加密 <br> * 每次加密的字节数,不能超过密钥的长度值减去11 * * @param data * 需加密数据的byte数据 * @param publicKey * 公钥 * @return 加密后的byte型数据 */ public static byte[] encryptData(byte[] data, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance(CIPHER); // 编码前设定编码方式及密钥 cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 传入编码数据并返回编码结果 return cipher.doFinal(data); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 用私钥解密 * * @param encryptedData * 经过encryptedData()加密返回的byte数据 * @param privateKey * 私钥 * @return */ public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(CIPHER); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(encryptedData); } catch (Exception e) { return null; } } /** * 通过公钥byte[](publicKey.getEncoded())将公钥还原,适用于RSA算法 * * @param keyBytes * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** * 通过私钥byte[]将公钥还原,适用于RSA算法 * * @param keyBytes * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 使用N、e值还原公钥 * * @param modulus * @param publicExponent * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PublicKey getPublicKey(String modulus, String publicExponent) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus); BigInteger bigIntPrivateExponent = new BigInteger(publicExponent); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** * 使用N、d值还原私钥 * * @param modulus * @param privateExponent * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey getPrivateKey(String modulus, String privateExponent) throws NoSuchAlgorithmException, InvalidKeySpecException { BigInteger bigIntModulus = new BigInteger(modulus); BigInteger bigIntPrivateExponent = new BigInteger(privateExponent); RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus, bigIntPrivateExponent); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 从字符串中加载公钥 * * @param publicKeyStr * 公钥数据字符串 * @throws Exception * 加载公钥时产生的异常 */ public static PublicKey loadPublicKey(String publicKeyStr) throws Exception { try { byte[] buffer = Base64Utils.decode(publicKeyStr); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); return keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("公钥非法"); } catch (NullPointerException e) { throw new Exception("公钥数据为空"); } } /** * 从字符串中加载私钥<br> * 加载时使用的是PKCS8EncodedKeySpec(PKCS#8编码的Key指令)。 * * @param privateKeyStr * @return * @throws Exception */ public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception { try { byte[] buffer = Base64Utils.decode(privateKeyStr); // X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance(KEY_PAIR); return keyFactory.generatePrivate(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("无此算法"); } catch (InvalidKeySpecException e) { throw new Exception("私钥非法"); } catch (NullPointerException e) { throw new Exception("私钥数据为空"); } } /** * 从文件中输入流中加载公钥 * * @param in * 公钥输入流 * @throws Exception * 加载公钥时产生的异常 */ public static PublicKey loadPublicKey(InputStream in) throws Exception { try { return loadPublicKey(readKey(in)); } catch (IOException e) { throw new Exception("公钥数据流读取错误"); } catch (NullPointerException e) { throw new Exception("公钥输入流为空"); } } /** * 从文件中加载私钥 * * @param * 私钥文件名 * @return 是否成功 * @throws Exception */ public static PrivateKey loadPrivateKey(InputStream in) throws Exception { try { return loadPrivateKey(readKey(in)); } catch (IOException e) { throw new Exception("私钥数据读取错误"); } catch (NullPointerException e) { throw new Exception("私钥输入流为空"); } } /** * 读取密钥信息 * -------------------- * CONTENT * -------------------- * @param in * @return * @throws IOException */ private static String readKey(InputStream in) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String readLine = null; StringBuilder sb = new StringBuilder(); while ((readLine = br.readLine()) != null) { if (readLine.charAt(0) == '-') { continue; } else { sb.append(readLine); sb.append('\r'); } } return sb.toString(); } }