Java RSA、AES加密样例代码

RSA加解密:

@Log4j
public class RSAMorliaCipher implements IMorliaCipher{
	
	private static final String RSA_PUB_KEY_STRING = "publickey";
	
	private static final String RSA_PRI_KEY_STRING = "privatekey";
	
	private static Cipher pubCipher = null;
	
	private static Cipher priCipher = null;
	
	static {
		try {
			//生成base64编码的公钥
			byte[] decoded = Base64.decodeBase64(RSA_PUB_KEY_STRING);
			RSAPublicKey publicKey2 = (RSAPublicKey) KeyFactory.getInstance("RSA")
					.generatePublic(new X509EncodedKeySpec(decoded));
			//RSA
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.PUBLIC_KEY, publicKey2);
			pubCipher = cipher;
		}catch (Exception e) {
			log.error("RSA public key cipher init failed!!");
		}
		
		try {
			//base64编码的私钥
			byte[] decoded = Base64.decodeBase64(RSA_PRI_KEY_STRING);
			RSAPrivateKey privateKey2 = (RSAPrivateKey) KeyFactory.getInstance("RSA")
					.generatePrivate(new PKCS8EncodedKeySpec(decoded));
			//RSA解密
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, privateKey2);
			priCipher = cipher;
		}catch (Exception e) {
			log.error("RSA private key cipher init failed!!");
		}
	}
	
	@Override
	public String encrypt(String data, String key) throws Exception {
		return Base64.encodeBase64String(pubCipher.doFinal(data.getBytes()));
	}

	@Override
	public String decrypt(String data, String key) throws Exception {
		return new String(priCipher.doFinal(Base64.decodeBase64(data.getBytes())));
	}
	
	public void generateKeyPair() throws NoSuchAlgorithmException {
		//KeyPairGenerator类用于生成私钥和公钥对,基于RSA算法
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
		//初始化秘钥对生成器,秘钥大小为96-1024
		keyPairGenerator.initialize(1024, new SecureRandom());
		//生成一个密钥对,
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		//生成私钥
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		//生成公钥
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		//生成公钥字符串
		String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
		//生成私钥字符串
		String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));
		log.debug(publicKeyString);
		log.debug(privateKeyString);
	}

	@Override
	public void registerCipher() {
		MorliaKeyFactory.registerCipher("RSA", new RSAMorliaCipher());
	}
}

RSA是长用的非对称加密算法,其规定每次加密的字节数,不能超过秘钥的长度值减去11,而每次加密得到的密文长度,却恰恰是秘钥的长度。所以,如果要加密较长的数据,可以采用数据截取的方法,分段加密。

AES是SecureRandom进行加解密:

@Log4j
public class AESRandomMorliaCipher implements IMorliaCipher{
	
	private static final String CIPHER_TYPE = "AES/ECB/PKCS5Padding";
	
	private static final String RANDOM_TYPE = "SHA1PRNG";
	
	private static final String CHAR_SET = "UTF-8";
	
	private static KeyGenerator keyGenerator = null;
	
	private static Cipher cipher = null;
	
	static {
		try {
			keyGenerator = KeyGenerator.getInstance("AES");
			cipher = Cipher.getInstance(CIPHER_TYPE);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			log.error("init AES random error!!");
		}
	}
	
	@Override
	public String encrypt(String data, String key) throws Exception {
		return Base64.encodeBase64String(cipher(data.getBytes(), key, Cipher.ENCRYPT_MODE));
	}

	@Override
	public String decrypt(String data, String key) throws Exception {
		return new String(cipher(Base64.decodeBase64(data), key, Cipher.DECRYPT_MODE),"UTF-8");
	}
	
	private byte[] cipher(byte[] data, String key, int mode) throws Exception {
		SecureRandom secureRandom = SecureRandom.getInstance(RANDOM_TYPE);
		secureRandom.setSeed(key.getBytes(CHAR_SET));
		keyGenerator.init(128, secureRandom);
		SecretKey secretKey = keyGenerator.generateKey();
		byte[] keyBytes = secretKey.getEncoded();
		
		Key key2 = new SecretKeySpec(keyBytes, "AES");
		cipher.init(mode, key2);
		
		return cipher.doFinal(data);
	}

	@Override
	public void registerCipher() {
		MorliaKeyFactory.registerCipher("AES-Random", new AESRandomMorliaCipher());
	}

}

如果是IOS客户端和JAVA服务器端交互,需要使用下面的IV向量加密。

AES使用IV向量来进行加解密:

@Log4j
public class AESIVMorliaCipher implements IMorliaCipher{

	private static final String CIPHER_TYPE = "AES/CBC/PKCS5Padding";
	
	private static final String IV_STRING = "------16bytes----";
	
	private static IvParameterSpec ivParameterSpec;
	
	private static Cipher cipher = null;
	
	static {
		try {
			cipher = Cipher.getInstance(CIPHER_TYPE);
			ivParameterSpec = new IvParameterSpec(IV_STRING.getBytes());
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			log.error("init AES IV error!!");
		}
	}

	@Override
	public String encrypt(String data, String key) throws Exception {
		return Base64.encodeBase64String(cipher(data.getBytes(), key, Cipher.ENCRYPT_MODE));
	}

	@Override
	public String decrypt(String data, String key) throws Exception {
		return new String(cipher(Base64.decodeBase64(data), key, Cipher.DECRYPT_MODE),"UTF-8");
	}
	
	private byte[] cipher(byte[] data, String key, int mode) throws Exception {
		byte[] keyBytes = key.getBytes();
		SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
		cipher.init(mode, secretKeySpec,ivParameterSpec);
		
		return cipher.doFinal(data);
	}

	@Override
	public void registerCipher() {
		MorliaKeyFactory.registerCipher("AES-IV", new AESIVMorliaCipher());
	}
}

此处加密的key是16位的,如果修改为32位或者更高位的的将会报java.security.InvalidKeyException: Illegal key size
解决办法:
下载对应的jar文件替换原有的,
jdk1.8的http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html。
其他版本的与之类似,下载好后解压,主要用到local_policy.jar和US_export_policy.jar,将其复制到JAVA_HOME下的\jre\lib\security中替换即可。

Factory工厂类通过包路径来自动注册算法对象

public interface IMorliaCipher {

	String encrypt(String data, String key) throws Exception;
	
	String decrypt(String data, String key) throws Exception;
	
	void registerCipher();
}
@Log4j
public class MorliaKeyFactory {
	
	private static final String CIPHER_BASE_INTERFACE = "IMorliaCipher";
	
	private static final String CIPHER_BASE_PACKAGE = "com.morlia.platform.common.init.encrypt.cipher";
	
	private static Map<String, IMorliaCipher> map = new HashMap<String, IMorliaCipher>();
	
	static {
		try {
			autoRegisterCipher();
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) {
			log.error("cipher init error!!" + e);
		}
	}
	
	public static void registerCipher(String cipherType, IMorliaCipher cipher) {
		map.put(cipherType, cipher);
	}
	
	private static void autoRegisterCipher() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
		List<String> classNameList = getClassNameFromPackge(CIPHER_BASE_PACKAGE);
		for(String className : classNameList) {
			Class<?> clazz = Class.forName(className);
			for(Class<?> class1 : clazz.getInterfaces()) {
				if(class1.getSimpleName().equals(CIPHER_BASE_INTERFACE)) {
					IMorliaCipher cipher = (IMorliaCipher) clazz.newInstance();
					cipher.registerCipher();
				}
			}
		}
	}
	
	private static List<String> getClassNameFromPackge(String packageName) throws IOException {
		List<String> returnClassList = new ArrayList<String>();
		
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		String strFile = packageName.replaceAll("\\.", "/");
		Enumeration<URL> urls = loader.getResources(strFile);
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			if(url != null) {
 				String pkgPath = url.getPath();
 		        File dirFile = new File(pkgPath);
 				if(!dirFile.exists() || !dirFile.isDirectory()) {
 			        log.warn("Cipher register failed!!");
 					return null;
 				}
 				 
 				File[] files = dirFile.listFiles(new FileFilter() {
					@Override
					public boolean accept(File file) {
						return file.getName().endsWith(".class");
					}
				});
 				 
 				for(File file : files) {
 					String className = file.getName().substring(0,file.getName().length() - 6);
 					returnClassList.add(packageName + "." + className);
 				}
			 }
		}
		return returnClassList;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值