From 3d886a5185a4476344572fabf9f5bfac6b8c8315 Mon Sep 17 00:00:00 2001 From: dushitaoyuan Date: Mon, 20 Jan 2020 12:57:32 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4rsa,=E5=A2=9E=E5=8A=A0aes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/ratelimit/GuavaRateLimiter.java | 6 +- .../taoyuanx/securitydemo/utils/AesUtil.java | 70 ++++++++++++++++ .../taoyuanx/securitydemo/utils/RSAUtil.java | 52 ++++++++---- .../taoyuanx/securitydemo/BoomFilterTest.java | 31 ++++--- .../com/taoyuanx/securitydemo/CertTest.java | 44 ---------- .../com/taoyuanx/securitydemo/EncodeTest.java | 80 +++++++++++++++++++ .../taoyuanx/securitydemo/PercentUtil.java | 19 +++++ 7 files changed, 229 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/taoyuanx/securitydemo/utils/AesUtil.java delete mode 100644 src/test/java/com/taoyuanx/securitydemo/CertTest.java create mode 100644 src/test/java/com/taoyuanx/securitydemo/EncodeTest.java create mode 100644 src/test/java/com/taoyuanx/securitydemo/PercentUtil.java diff --git a/src/main/java/com/taoyuanx/securitydemo/security/ratelimit/GuavaRateLimiter.java b/src/main/java/com/taoyuanx/securitydemo/security/ratelimit/GuavaRateLimiter.java index 40c2bbf..799391f 100644 --- a/src/main/java/com/taoyuanx/securitydemo/security/ratelimit/GuavaRateLimiter.java +++ b/src/main/java/com/taoyuanx/securitydemo/security/ratelimit/GuavaRateLimiter.java @@ -22,8 +22,9 @@ public class GuavaRateLimiter extends AbstractRateLimiter { /** * 总数限流到0后,标记,会有些许误判,不在乎内存的话,可用hashset存 */ - private BloomFilter TOTAL_LIMIT_ZERO_FLAG = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), MAX_HOLDER_SIZE * 20); + private BloomFilter TOTAL_LIMIT_ZERO_FLAG = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), MAX_HOLDER_SIZE * 20, 0.001); + @Override public boolean doTryAcquire(int permits, String key, Double limit) { //超过固定阈值,清空,重构 if (rateHolder.size() > MAX_HOLDER_SIZE) { @@ -32,8 +33,9 @@ public class GuavaRateLimiter extends AbstractRateLimiter { RateLimiter rateLimiter = null; if (rateHolder.containsKey(key)) { rateLimiter = rateHolder.get(key); + } else { + rateLimiter = RateLimiter.create(limit); } - rateLimiter = RateLimiter.create(limit); rateHolder.putIfAbsent(key, rateLimiter); return rateLimiter.tryAcquire(permits); } diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/AesUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/AesUtil.java new file mode 100644 index 0000000..2ee50ee --- /dev/null +++ b/src/main/java/com/taoyuanx/securitydemo/utils/AesUtil.java @@ -0,0 +1,70 @@ +package com.taoyuanx.securitydemo.utils; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author dushitaoyuan + * @desc aes 加密 + * @date 2020/1/20 + */ +public class AesUtil { + private static final byte[] iv = "0000000000000000".getBytes(); + private static final String AES_MODE = "AES/CBC/PKCS5Padding"; + private static Integer cacheSize = 1024 * 1024; + + public static byte[] encrypt(byte[] data, String password) throws Exception { + SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AES_MODE); + cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); + byte[] result = cipher.doFinal(data); + return result; + } + + + public static byte[] decrypt(byte[] data, String password) throws Exception { + SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AES_MODE); + cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + byte[] result = cipher.doFinal(data); + return result; + } + + + public static void encrypt(InputStream dataStream, String password, OutputStream encodeStream) throws Exception { + SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AES_MODE); + cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); + CipherInputStream cipherInputStream = new CipherInputStream(dataStream, cipher); + byte[] buf = new byte[cacheSize]; + int len = 0; + while ((len = cipherInputStream.read(buf)) != -1) { + encodeStream.write(buf, 0, len); + encodeStream.flush(); + } + encodeStream.close(); + cipherInputStream.close(); + } + + + public static void decrypt(InputStream encodeStream, String password, OutputStream decodeStream) throws Exception { + SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES"); + Cipher cipher = Cipher.getInstance(AES_MODE); + cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + CipherOutputStream cipherOutputStream = new CipherOutputStream(decodeStream, cipher); + byte[] buf = new byte[cacheSize]; + int len = 0; + while ((len = encodeStream.read(buf)) != -1) { + cipherOutputStream.write(buf, 0, len); + cipherOutputStream.flush(); + } + cipherOutputStream.close(); + decodeStream.close(); + encodeStream.close(); + } +} diff --git a/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java b/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java index 4fc0b03..9d35428 100644 --- a/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java +++ b/src/main/java/com/taoyuanx/securitydemo/utils/RSAUtil.java @@ -98,12 +98,12 @@ public final class RSAUtil { int key_len = publicKey.getModulus().bitLength() / 8; // 加密数据长度 <= 模长-11,如果明文长度大于模长-11则要分组加密 key_len -= 11; - byte[] dataReturn = null; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); for (int i = 0; i < data.length; i += key_len) { byte[] doFinal = cipher.doFinal(HelperUtil.subarray(data, i, i + key_len)); - dataReturn = HelperUtil.addAll(dataReturn, doFinal); + outputStream.write(doFinal); } - return dataReturn; + return outputStream.toByteArray(); } @@ -139,37 +139,55 @@ public final class RSAUtil { } - public static void encryptByPublicKey(InputStream data, RSAPublicKey publicKey, OutputStream encodeStream) throws Exception { + public static void encryptByPublicKey(InputStream dataStream, RSAPublicKey publicKey, OutputStream encodeStream) throws Exception { if (null == publicKey) { throw new Exception("rsa publicKey is null"); } Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); cipher.init(Cipher.ENCRYPT_MODE, publicKey); - CipherInputStream cipherInputStream = new CipherInputStream(data, cipher); - int buffSize = 4 << 20; + // 计算分组长度 + int key_len = publicKey.getModulus().bitLength() / 8 - 11; + int buffSize = key_len * 1024; byte[] buf = new byte[buffSize]; - int len = 0; - while ((len = cipherInputStream.read(buf)) != -1) { - encodeStream.write(buf, 0, len); + int len = 0, end = 0; + while ((len = dataStream.read(buf)) != -1) { + for (int start = 0; start < len; start += key_len) { + end = start + key_len; + if (end > len) { + end = len; + } + byte[] doFinal = cipher.doFinal(HelperUtil.subarray(buf, start, end)); + encodeStream.write(doFinal, 0, doFinal.length); + } } - cipherInputStream.close(); + dataStream.close(); + encodeStream.close(); } - public static void decryptByPrivateKey(InputStream data, RSAPrivateKey privateKey, OutputStream decodeStream) throws Exception { + public static void decryptByPrivateKey(InputStream dataStream, RSAPrivateKey privateKey, OutputStream decodeStream) throws Exception { if (null == privateKey) { throw new Exception("rsa privateKey is null"); } Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE_RSA); cipher.init(Cipher.DECRYPT_MODE, privateKey); - CipherOutputStream cipherOutputStream = new CipherOutputStream(decodeStream, cipher); - int buffSize = 4 << 20; + // 计算分组长度 + int key_len = privateKey.getModulus().bitLength() / 8; + int buffSize = key_len * 1024; byte[] buf = new byte[buffSize]; - int len = 0; - while ((len = data.read(buf)) != -1) { - cipherOutputStream.write(buf, 0, len); + int len = 0, end = 0; + while ((len = dataStream.read(buf)) != -1) { + for (int start = 0; start < len; start += key_len) { + end = start + key_len; + if (end > len) { + end = len; + } + byte[] doFinal = cipher.doFinal(HelperUtil.subarray(buf, start, end)); + decodeStream.write(doFinal, 0, doFinal.length); + } } - cipherOutputStream.close(); + dataStream.close(); + decodeStream.close(); } diff --git a/src/test/java/com/taoyuanx/securitydemo/BoomFilterTest.java b/src/test/java/com/taoyuanx/securitydemo/BoomFilterTest.java index 241e80d..767ad19 100644 --- a/src/test/java/com/taoyuanx/securitydemo/BoomFilterTest.java +++ b/src/test/java/com/taoyuanx/securitydemo/BoomFilterTest.java @@ -10,6 +10,9 @@ import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.HashMap; import java.util.Map; @@ -22,28 +25,36 @@ public class BoomFilterTest { @Test public void failedCountTest() { - int batch = 10000000; - BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(), batch); + int batch = 100000; + BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(), batch, 0.0001); for (int i = 0; i < batch; i++) { bloomFilter.put(i); } - int count = 0; - for (int i = 0; i < batch; i++) { - if (!bloomFilter.mightContain(i)) { - System.out.println("failed\t" + i); + int count = 0, max = batch * 10; + for (int i = 0; i < max; i++) { + if (i < batch && !bloomFilter.mightContain(i)) { + System.out.println("误判 \t" + i); + count++; + } + if (i > batch && bloomFilter.mightContain(i)) { + System.out.println("误判 \t" + i); count++; } } - System.out.println("失败次数:" + count); + System.out.println("失败次数:" + count + "错误率:" + PercentUtil.percent(Double.valueOf(count), Double.valueOf(max), 2)); } + + + + @Test - public void testEl(){ - String el="${m}"; + public void testEl() { + String el = "${m}"; ExpressionParser parser = new SpelExpressionParser(); EvaluationContext context = new StandardEvaluationContext(); - context.setVariable("m","1234"); + context.setVariable("m", "1234"); Expression expression = parser.parseExpression(el); diff --git a/src/test/java/com/taoyuanx/securitydemo/CertTest.java b/src/test/java/com/taoyuanx/securitydemo/CertTest.java deleted file mode 100644 index c6540fe..0000000 --- a/src/test/java/com/taoyuanx/securitydemo/CertTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.taoyuanx.securitydemo; - -import com.taoyuanx.securitydemo.utils.HashUtil; -import com.taoyuanx.securitydemo.utils.HelperUtil; -import com.taoyuanx.securitydemo.utils.RSAUtil; -import org.junit.Test; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.security.KeyStore; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; - -/** - * @author dushitaoyuan - * @date 2020/1/15 - */ -public class CertTest { - @Test - public void rsaTest() throws Exception { - - - KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); - RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); - RSAUtil.getPrivateKey(keyStore, "123456"); - - } - - @Test - public void rsaDecodeFileTest() throws Exception { - - KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); - RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); - RSAPrivateKey privateKey = RSAUtil.getPrivateKey(keyStore, "123456"); - String srcFile = "d://demo.pdf", encodeFile = "d://demo_encode.pdf", decodeFile = "d://demo_decode.pdf"; - String fileHash = HashUtil.hash(new FileInputStream(srcFile), HashUtil.MD5, HashUtil.HEX); - RSAUtil.encryptByPublicKey(new FileInputStream(srcFile), publicKey, new FileOutputStream(encodeFile)); - RSAUtil.decryptByPrivateKey(new FileInputStream(encodeFile), privateKey, new FileOutputStream(decodeFile)); - - String fileEncodeHash = HashUtil.hash(new FileInputStream(decodeFile), HashUtil.MD5, HashUtil.HEX); - System.out.println(fileHash.equals(fileEncodeHash)); - - } -} diff --git a/src/test/java/com/taoyuanx/securitydemo/EncodeTest.java b/src/test/java/com/taoyuanx/securitydemo/EncodeTest.java new file mode 100644 index 0000000..da104ac --- /dev/null +++ b/src/test/java/com/taoyuanx/securitydemo/EncodeTest.java @@ -0,0 +1,80 @@ +package com.taoyuanx.securitydemo; + +import com.google.common.base.Charsets; +import com.google.common.hash.HashCode; +import com.google.common.hash.Hashing; +import com.taoyuanx.securitydemo.utils.AesUtil; +import com.taoyuanx.securitydemo.utils.HashUtil; +import com.taoyuanx.securitydemo.utils.RSAUtil; +import org.apache.commons.io.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyStore; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +/** + * @author dushitaoyuan + * @date 2020/1/15 + */ +public class EncodeTest { + @Test + public void rsaTest() throws Exception { + + + KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); + RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); + RSAUtil.getPrivateKey(keyStore, "123456"); + + + } + + @Test + public void rsaDecodeFileTest() throws Exception { + + KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); + RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); + RSAPrivateKey privateKey = RSAUtil.getPrivateKey(keyStore, "123456"); + String srcFile = "d://demo.pdf", encodeFile = "d://demo_encode.pdf", decodeFile = "d://demo_decode.pdf"; + String fileHash = HashUtil.hash(new FileInputStream(srcFile), HashUtil.MD5, HashUtil.HEX); + RSAUtil.encryptByPublicKey(new FileInputStream(srcFile), publicKey, new FileOutputStream(encodeFile)); + RSAUtil.decryptByPrivateKey(new FileInputStream(encodeFile), privateKey, new FileOutputStream(decodeFile)); + + String fileEncodeHash = HashUtil.hash(new FileInputStream(decodeFile), HashUtil.MD5, HashUtil.HEX); + System.out.println(fileHash.equals(fileEncodeHash)); + + } + + @Test + public void rsaFileTest() throws Exception { + + KeyStore keyStore = RSAUtil.getKeyStore("d://client.p12", "123456"); + RSAPublicKey publicKey = RSAUtil.getPublicKey(keyStore); + RSAPrivateKey privateKey = RSAUtil.getPrivateKey(keyStore, "123456"); + String srcFile = "d://demo.pdf", encodeFile = "d://demo_encode.pdf", decodeFile = "d://demo_decode.pdf"; + String fileHash = HashUtil.hash(new FileInputStream(srcFile), HashUtil.MD5, HashUtil.HEX); + byte[] bytes = RSAUtil.encryptByPublicKey(FileUtils.readFileToByteArray(new File(srcFile)), publicKey); + FileUtils.writeByteArrayToFile(new File(encodeFile), bytes); + bytes = RSAUtil.decryptByPrivateKey(bytes, privateKey); + FileUtils.writeByteArrayToFile(new File(decodeFile), bytes); + String fileEncodeHash = HashUtil.hash(new FileInputStream(decodeFile), HashUtil.MD5, HashUtil.HEX); + System.out.println(fileHash.equals(fileEncodeHash)); + + } + + @Test + public void aesFileTest() throws Exception { + String srcFile = "d://demo.pdf", encodeFile = "d://demo_encode.pdf", decodeFile = "d://demo_decode.pdf"; + String password="1234567812345678"; + String fileHash = HashUtil.hash(new FileInputStream(srcFile), HashUtil.MD5, HashUtil.HEX); + AesUtil.encrypt(new FileInputStream(srcFile), password, new FileOutputStream(encodeFile)); + AesUtil.decrypt(new FileInputStream(encodeFile), password, new FileOutputStream(decodeFile)); + + String fileEncodeHash = HashUtil.hash(new FileInputStream(decodeFile), HashUtil.MD5, HashUtil.HEX); + System.out.println(fileHash.equals(fileEncodeHash)); + + } +} diff --git a/src/test/java/com/taoyuanx/securitydemo/PercentUtil.java b/src/test/java/com/taoyuanx/securitydemo/PercentUtil.java new file mode 100644 index 0000000..770a446 --- /dev/null +++ b/src/test/java/com/taoyuanx/securitydemo/PercentUtil.java @@ -0,0 +1,19 @@ +package com.taoyuanx.securitydemo; + +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.text.NumberFormat; + +/** + * @author dushitaoyuan + * @date 2020/1/20 + */ +public class PercentUtil { + public static String percent(double num, double total, int scale) { + DecimalFormat format = (DecimalFormat) NumberFormat.getPercentInstance(); + format.setMaximumFractionDigits(scale); + format.setRoundingMode(RoundingMode.HALF_UP); + double percent = num / total; + return format.format(percent); + } +}