├── .gitignore ├── LICENSE ├── README.md ├── imgs ├── aes │ ├── AddRoundKey.jpg │ ├── ShiftRows.png │ ├── SubBytes.png │ ├── big.png │ ├── bm.png │ ├── bm2.png │ ├── encryption.png │ ├── inverSBox.png │ ├── inversesb.png │ ├── keySelection1.png │ ├── mc.png │ ├── nb1.png │ ├── nb2.png │ ├── nb3.png │ ├── sbb.png │ ├── sbsb.png │ ├── state1.png │ ├── subbytes1.png │ └── xt2.png ├── des │ ├── R23.png │ ├── desMain.png │ ├── desView4.png │ ├── desView5.png │ ├── e.png │ ├── hs1.png │ ├── hs2.png │ ├── ip.png │ ├── is.png │ ├── p.png │ ├── replaceselect1.png │ ├── sb.png │ ├── sbox.png │ └── subkeysgeneration.gif └── rsa-gui.png ├── pom.xml └── src ├── main └── java │ └── org │ └── jordon │ └── security │ ├── App.java │ ├── attack │ ├── cryptanalysis │ │ └── DESDifferential.java │ └── statistics │ │ └── DESStatistics.java │ ├── constant │ ├── AESConstants.java │ └── DESConstants.java │ ├── core │ ├── crypto │ │ ├── CipherService.java │ │ ├── assymmetry │ │ │ ├── RSACipherService.java │ │ │ └── RawRSACipherService.java │ │ └── symmetry │ │ │ ├── AESCipherService.java │ │ │ ├── DESCipherService.java │ │ │ └── RC4CipherService.java │ └── hash │ │ ├── IHash.java │ │ ├── SHA1.java │ │ ├── SHA1Digest.java │ │ └── SM3.java │ ├── util │ ├── ArrayUtil.java │ ├── Base64Util.java │ ├── MathUtil.java │ └── PrimalityTester.java │ └── view │ ├── AESView.java │ ├── AESView.jfd │ ├── DESView.java │ ├── DESView.jfd │ ├── RSABigIntegerView.java │ ├── RSABigIntegerView.jfd │ ├── RSAView.java │ └── RSAView.jfd └── test └── java └── org └── jordon └── security ├── AppTest.java ├── ByteTest.java ├── RSATest.java └── core ├── CipherServiceTest.java ├── DESCipherServiceTest.java ├── RC4CipherServiceTest.java └── crypto └── assymmetry ├── RSACipherServiceTest.java └── RawRSACipherServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | 7 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 8 | hs_err_pid* 9 | # Compiled class file 10 | # Log file 11 | *.log 12 | 13 | # BlueJ files 14 | *.ctxt 15 | 16 | # Mobile Tools for Java (J2ME) 17 | .mtj.tmp/ 18 | 19 | # Package Files # 20 | # *.jar 21 | # *.war 22 | # *.ear 23 | # *.zip 24 | # *.tar.gz 25 | # *.rar 26 | 27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 28 | hs_err_pid* 29 | 30 | # maven 31 | /**/target 32 | 33 | # idea 34 | /**/.idea 35 | /**/mvnw 36 | /**/mvnw.cmd 37 | /out 38 | /**/*.iml 39 | *.ipr 40 | *.iws 41 | /**/.mvn/ 42 | 43 | # IDEA metadata and output dirs 44 | # eclipse 45 | .settings 46 | .project 47 | .classpath 48 | .log 49 | 50 | # Package Files 51 | *.bak 52 | *.tmp 53 | /bin 54 | 55 | !webapp/WEB-INF/web.xml 56 | webapp/ 57 | 58 | # windows 59 | Thumbs.db 60 | 61 | # Mac 62 | .DS_Store 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jordon Yang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /imgs/aes/AddRoundKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/AddRoundKey.jpg -------------------------------------------------------------------------------- /imgs/aes/ShiftRows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/ShiftRows.png -------------------------------------------------------------------------------- /imgs/aes/SubBytes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/SubBytes.png -------------------------------------------------------------------------------- /imgs/aes/big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/big.png -------------------------------------------------------------------------------- /imgs/aes/bm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/bm.png -------------------------------------------------------------------------------- /imgs/aes/bm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/bm2.png -------------------------------------------------------------------------------- /imgs/aes/encryption.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/encryption.png -------------------------------------------------------------------------------- /imgs/aes/inverSBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/inverSBox.png -------------------------------------------------------------------------------- /imgs/aes/inversesb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/inversesb.png -------------------------------------------------------------------------------- /imgs/aes/keySelection1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/keySelection1.png -------------------------------------------------------------------------------- /imgs/aes/mc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/mc.png -------------------------------------------------------------------------------- /imgs/aes/nb1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/nb1.png -------------------------------------------------------------------------------- /imgs/aes/nb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/nb2.png -------------------------------------------------------------------------------- /imgs/aes/nb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/nb3.png -------------------------------------------------------------------------------- /imgs/aes/sbb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/sbb.png -------------------------------------------------------------------------------- /imgs/aes/sbsb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/sbsb.png -------------------------------------------------------------------------------- /imgs/aes/state1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/state1.png -------------------------------------------------------------------------------- /imgs/aes/subbytes1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/subbytes1.png -------------------------------------------------------------------------------- /imgs/aes/xt2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/aes/xt2.png -------------------------------------------------------------------------------- /imgs/des/R23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/R23.png -------------------------------------------------------------------------------- /imgs/des/desMain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/desMain.png -------------------------------------------------------------------------------- /imgs/des/desView4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/desView4.png -------------------------------------------------------------------------------- /imgs/des/desView5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/desView5.png -------------------------------------------------------------------------------- /imgs/des/e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/e.png -------------------------------------------------------------------------------- /imgs/des/hs1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/hs1.png -------------------------------------------------------------------------------- /imgs/des/hs2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/hs2.png -------------------------------------------------------------------------------- /imgs/des/ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/ip.png -------------------------------------------------------------------------------- /imgs/des/is.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/is.png -------------------------------------------------------------------------------- /imgs/des/p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/p.png -------------------------------------------------------------------------------- /imgs/des/replaceselect1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/replaceselect1.png -------------------------------------------------------------------------------- /imgs/des/sb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/sb.png -------------------------------------------------------------------------------- /imgs/des/sbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/sbox.png -------------------------------------------------------------------------------- /imgs/des/subkeysgeneration.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/des/subkeysgeneration.gif -------------------------------------------------------------------------------- /imgs/rsa-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cszxyang/cipher4j/33e24b4f7534468ab9e5863e17b5b148053e1098/imgs/rsa-gui.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | org.jordon.security 8 | cipher4j 9 | 1.0 10 | 11 | cipher4j 12 | 13 | http://www.example.com 14 | 15 | 16 | UTF-8 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | 24 | commons-codec 25 | commons-codec 26 | 1.11 27 | 28 | 29 | 30 | org.projectlombok 31 | lombok 32 | 1.18.2 33 | provided 34 | 35 | 36 | 37 | junit 38 | junit 39 | 4.11 40 | test 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | maven-clean-plugin 49 | 3.0.0 50 | 51 | 52 | 53 | maven-resources-plugin 54 | 3.0.2 55 | 56 | 57 | maven-compiler-plugin 58 | 3.7.0 59 | 60 | 61 | maven-surefire-plugin 62 | 2.20.1 63 | 64 | 65 | maven-jar-plugin 66 | 3.0.2 67 | 68 | 69 | maven-install-plugin 70 | 2.5.2 71 | 72 | 73 | maven-deploy-plugin 74 | 2.8.2 75 | 76 | 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-compiler-plugin 82 | 83 | 8 84 | 8 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/App.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security; 2 | 3 | /** 4 | * app entry 5 | */ 6 | public class App { 7 | public static void main( String[] args ) { 8 | System.out.println( "Hello World!" ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/attack/cryptanalysis/DESDifferential.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.attack.cryptanalysis; 2 | 3 | import org.jordon.security.constant.DESConstants; 4 | import org.jordon.security.util.ArrayUtil; 5 | 6 | public class DESDifferential { 7 | 8 | private short inputDiff; 9 | 10 | public DESDifferential(short inputDiff) { 11 | this.inputDiff = inputDiff; 12 | } 13 | 14 | /** 15 | * differential cryptanalysis 16 | */ 17 | public void analyze() { 18 | // 选定输入查分为000001 19 | short[][] diffPairs = genDiffInputPairs(inputDiff); 20 | if (diffPairs != null) { 21 | printPairs(diffPairs); 22 | // 经过S盒子 23 | System.out.println("\n输出差分"); 24 | 25 | StringBuilder[] builders = new StringBuilder[16]; 26 | for (int i = 0; i < builders.length; i++) { 27 | builders[i] = new StringBuilder(); 28 | } 29 | for (int i = 1; i <= diffPairs.length; i++) { 30 | short s = (short) (sub(getBinStr(diffPairs[i - 1][0])) ^ sub(getBinStr(diffPairs[i - 1][1]))); 31 | String symbol = i % 8 == 0 ? "\n" : " "; 32 | System.out.print(getOutput(s) + symbol); 33 | 34 | builders[s].append(getOutput(s)).append(" "); 35 | } 36 | System.out.println("\n差分输出分布"); 37 | for (int i = 0; i < builders.length; i++){ 38 | ArrayUtil.printInfo(getOutput((short) i), builders[i].toString(), false); 39 | } 40 | } 41 | } 42 | 43 | private String getOutput(short output) { 44 | if (output == 0) { 45 | return "0000"; 46 | }else if (output == 1) { 47 | return "0001"; 48 | } 49 | return Integer.toBinaryString((output & 0b1111) + 0b10000).substring(1, 5); 50 | } 51 | 52 | private short sub(String val) { 53 | char[] chars = val.toCharArray(); 54 | char[] rowBits = { 55 | chars[0], 56 | chars[5] 57 | }; 58 | char[] columnBits = { 59 | chars[1], chars[2], 60 | chars[3], chars[4] 61 | }; 62 | 63 | int rowIndex = Integer.parseInt(String.valueOf(rowBits), 2); 64 | int columnIndex = Integer.parseInt(String.valueOf(columnBits), 2); 65 | // (3) obtain output of Si 66 | return DESConstants.SUBSTITUTE_BOX[0][rowIndex][columnIndex]; 67 | } 68 | 69 | /** 70 | * 根据指定输入差分,生成所有明文输入对 71 | */ 72 | private short[][] genDiffInputPairs(short inputDiff) { 73 | // 2^6 74 | System.out.println("输入差分:" + getBinStr(inputDiff)); 75 | if (inputDiff >= 0x00 && inputDiff <= 0x0f) { 76 | short[] pair = {0, inputDiff}; 77 | short[][] pairs = new short[64][2]; 78 | pairs[0] = pair; 79 | 80 | for (short i = 1; i < 64; i++) { 81 | pairs[i] = new short[]{i, (short) (i ^ inputDiff)}; 82 | } 83 | return pairs; 84 | } 85 | return null; 86 | } 87 | 88 | private void printPairs(short[][] pairs) { 89 | System.out.println("\n输入对"); 90 | for (int i = 1; i <= pairs.length; i++) { 91 | String symbol = i % 8 == 0 ? "\n" : " "; 92 | System.out.print("(" + getBinStr(pairs[i - 1][0]) + 93 | "," + getBinStr(pairs[i - 1][1]) + ")" + symbol); 94 | } 95 | } 96 | 97 | private String getBinStr(short val) { 98 | if (val == 0) { 99 | return "000000"; 100 | }else if (val == 1) { 101 | return "000001"; 102 | } 103 | return Integer.toBinaryString((val & 0b111111) + 0b1000000).substring(1, 7); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/attack/statistics/DESStatistics.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.attack.statistics; 2 | 3 | import org.jordon.security.core.crypto.symmetry.DESCipherService; 4 | 5 | import java.security.SecureRandom; 6 | 7 | public class DESStatistics { 8 | 9 | private DESCipherService desService; 10 | 11 | private int testCount; 12 | 13 | public DESStatistics(int testCount) { 14 | this.desService = new DESCipherService(false); 15 | this.testCount = testCount; 16 | } 17 | 18 | /** 19 | * 顺序统计明文/密钥改变n位,对应密文改变位数 20 | */ 21 | public void run() { 22 | countRounds(testCount); 23 | } 24 | 25 | /** 26 | * 进行n次测试统计,取平均值(明文&密钥变化) 27 | * @param testCount 测试次数 28 | */ 29 | private void countRounds(int testCount) { 30 | double[][] keyChangeResult = new double[testCount][64]; 31 | double[][] plaintextChangeResult = new double[testCount][64]; 32 | 33 | for (int i = 0; i < testCount; i++) { 34 | keyChangeResult[i] = countOneRound(true); 35 | plaintextChangeResult[i] = countOneRound(false); 36 | } 37 | 38 | double[] keyAvg = new double[64]; 39 | double[] plaintextAvg = new double[64]; 40 | 41 | for (int i = 0; i < 64; i++) { 42 | for (int j = 0; j < testCount; j++) { 43 | keyAvg[i] += keyChangeResult[j][i]; 44 | plaintextAvg[i] += plaintextChangeResult[j][i]; 45 | } 46 | keyAvg[i] /= testCount; 47 | plaintextAvg[i] /= testCount; 48 | } 49 | 50 | for (int i = 0 ; i < testCount; i++) { 51 | double avg4Key = 0; 52 | System.out.println("第" + (i + 1) + "次测试"); 53 | System.out.println(String.format("%-25s%-30s", "密钥改变位数", "密文改变位数")); 54 | for (int j = 0; j < 64; j++) { 55 | System.out.println(String.format("%-30s%-30s", (j + 1), 56 | keyChangeResult[i][j])); 57 | avg4Key += keyChangeResult[i][j]; 58 | } 59 | System.out.println("均值:" + (avg4Key / 64) + "\n"); 60 | } 61 | 62 | System.out.println(testCount + "次密钥改变, 密文位数改变均值"); 63 | System.out.println(String.format("%-25s%-30s", "密钥改变位数", "密文平均改变位数")); 64 | for (int j = 0; j < 64; j++) { 65 | System.out.println(String.format("%-30s%-30s", (j + 1), keyAvg[j])); 66 | } 67 | 68 | 69 | for (int i = 0 ; i < testCount; i++) { 70 | double plaintAvg = 0; 71 | System.out.println("第" + (i + 1) + "次测试"); 72 | System.out.println(String.format("%-25s%-30s", "明文改变位数", "密文改变位数")); 73 | for (int j = 0; j < 64; j++) { 74 | System.out.println(String.format("%-30s%-30s", (j + 1), 75 | plaintextChangeResult[i][j])); 76 | plaintAvg += plaintextChangeResult[i][j]; 77 | } 78 | System.out.println("均值:" + (plaintAvg / 64) + "\n"); 79 | } 80 | 81 | System.out.println("统计" + testCount + "次明文改变, 密文位数改变均值"); 82 | System.out.println(String.format("%-25s%-30s", "明文改变位数", "密文平均改变位数")); 83 | for (int j =0; j < 64; j++) { 84 | System.out.println(String.format("%-30s%-30s", (j + 1), plaintextAvg[j])); 85 | } 86 | } 87 | 88 | /** 89 | * 统计密钥/明文改变1, 2,..., 64位,密文相应改变的位数 90 | * @param processKeyChange 为了复用该方法, 标记位改变的是明文还是密钥 91 | * @return 密钥/明文改变64次,密文相应改变的位数 92 | */ 93 | private double[] countOneRound(boolean processKeyChange) { 94 | char[] plaintext = ran64Bits(); 95 | char[] originKey = ran64Bits(); 96 | char[] firstResult = desService.encode(plaintext, desService.generateSubKeys(originKey)); 97 | 98 | // 用来存放每次位数变化,相应数据(明文或密钥)变化的位数 99 | double[] changedBits = new double[64]; 100 | for (int i = 1; i <= 64; i++) { 101 | char[] negation, result; 102 | if (processKeyChange) { // 处理密钥位变化 103 | negation = bitNegation(i, originKey); 104 | result = desService.encode(plaintext, desService.generateSubKeys(negation)); 105 | }else { // 处理明文位变化 106 | negation = bitNegation(i, plaintext); 107 | result = desService.encode(negation, desService.generateSubKeys(originKey)); 108 | } 109 | changedBits[i - 1] = compare(firstResult, result); 110 | } 111 | return changedBits; 112 | } 113 | 114 | /** 115 | * 对比第一次加密得到的密文和明文/密钥改变n位得到的密文, 统计差异位数 116 | * @param firstResult 第一次加密得到的密文 117 | * @param changedResult 明文/密钥改变n位得到的密文 118 | * @return 两者之间差异的位数 119 | */ 120 | private int compare(char[] firstResult, char[] changedResult) { 121 | int counter = 0; 122 | for (int i = 0; i < 64; i++) { 123 | if (firstResult[i] != changedResult[i]) { 124 | counter ++; 125 | } 126 | } 127 | return counter; 128 | } 129 | 130 | /** 131 | * 将原比特字符数组的相应位数”逻辑取反“ 132 | * @param bitCount 从高位数起要取反的位数 133 | * @param origin 比特字符数组(明文或密钥) 134 | * @return 取反结果 135 | */ 136 | private char[] bitNegation(int bitCount, char[] origin) { 137 | char[] result = new char[64]; 138 | for (int i = 0; i < bitCount; i++) { 139 | result[i] = bitNegation(origin[i]); 140 | } 141 | System.arraycopy(origin, bitCount, result, bitCount, 64 - bitCount); 142 | return result; 143 | } 144 | 145 | /** 146 | * 随机产生64位数据 147 | * @return 64位数据组 148 | */ 149 | private char[] ran64Bits() { 150 | char[] result = new char[64]; 151 | SecureRandom secureRandom = new SecureRandom(); 152 | for (int i = 0; i < 64; i++) { 153 | result[i] = secureRandom.nextBoolean() ? '1' :'0'; 154 | } 155 | return result; 156 | } 157 | 158 | /** 159 | * 比特位取反 160 | * @param bit char类型的比特数据 161 | * @return 取反后的比特数据 162 | */ 163 | private char bitNegation(char bit) { 164 | return bit == '0' ? '1' : '0'; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/constant/AESConstants.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.constant; 2 | 3 | public interface AESConstants { 4 | 5 | // irreducible polynomial C(x)=03x^3+01x^2+01^2+01x+02 6 | // which is replaced as a constant table 7 | short[][] CX = { 8 | {0x02, 0x03, 0x01, 0x01}, 9 | {0x01, 0x02, 0x03, 0x01}, 10 | {0x01, 0x01, 0x02, 0x03}, 11 | {0x03, 0x01, 0x01, 0x02}, 12 | }; 13 | 14 | // irreducible polynomial in inverse operation of 15 | // C(x)=03x^3+01x^2+01^2+01x+02, replaced as an inverse 16 | // matrix of CX 17 | short[][] INVERSE_CX = { 18 | {0x0E, 0x0B, 0x0D, 0x09}, 19 | {0x09, 0x0E, 0x0B, 0x0D}, 20 | {0x0D, 0x09, 0x0E, 0x0B}, 21 | {0x0B, 0x0D, 0x09, 0x0E}, 22 | }; 23 | 24 | // an indexing table for ring shifting left a word using byte as a unit 25 | // in generateRoundKeys operation of encryption 26 | short[] LEFT_SHIFT_TABLE = {1, 2, 3, 0}; 27 | 28 | // an indexing table for ring shifting left a word using byte as a unit 29 | // in generateRoundKeys operation of decryption 30 | short[] INVERSE_LEFT_SHIFT_TABLE = {1, 2, 3, 0}; 31 | 32 | // 轮常数数组 33 | // round constant matrix 34 | short[][] R_CON = { 35 | {0x00, 0x00, 0x00, 0x00}, 36 | {0x01, 0x00, 0x00, 0x00}, 37 | {0x02, 0x00, 0x00, 0x00}, 38 | {0x04, 0x00, 0x00, 0x00}, 39 | {0x08, 0x00, 0x00, 0x00}, 40 | {0x10, 0x00, 0x00, 0x00}, 41 | {0x20, 0x00, 0x00, 0x00}, 42 | {0x40, 0x00, 0x00, 0x00}, 43 | {0x80, 0x00, 0x00, 0x00}, 44 | {0x1b, 0x00, 0x00, 0x00}, 45 | {0x36, 0x00, 0x00, 0x00}, 46 | }; 47 | 48 | // 加密操作行移位变换中决定字间字节循环左移规则的矩阵 49 | // shifting rules for row shifting in encryption 50 | short[][] SHIFTING_TABLE = { 51 | {0, 1, 2, 3}, 52 | {1, 2 ,3, 0}, 53 | {2, 3, 0, 1}, 54 | {3, 0, 1, 2}, 55 | }; 56 | 57 | // 解密操作行移位变换中决定字间字节循环左移规则的矩阵 58 | // shifting rules for row shifting in decryption 59 | short[][] INVERSE_SHIFTING_TABLE = { 60 | {0, 3, 2, 1}, 61 | {1, 0 ,3, 2}, 62 | {2, 1, 0, 3}, 63 | {3, 2, 1, 0}, 64 | }; 65 | 66 | // selection table for byte substitution in encryption 67 | short[][] SUBSTITUTE_BOX = { 68 | {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76}, 69 | {0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0}, 70 | {0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15}, 71 | {0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75}, 72 | {0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84}, 73 | {0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf}, 74 | {0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8}, 75 | {0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2}, 76 | {0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73}, 77 | {0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb}, 78 | {0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79}, 79 | {0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08}, 80 | {0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a}, 81 | {0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e}, 82 | {0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf}, 83 | {0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}, 84 | }; 85 | 86 | // selection table for byte substitution in decryption 87 | short[][] INVERSE_SUBSTITUTE_BOX = { 88 | {0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb}, 89 | {0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb}, 90 | {0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e}, 91 | {0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25}, 92 | {0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92}, 93 | {0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84}, 94 | {0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06}, 95 | {0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b}, 96 | {0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73}, 97 | {0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e}, 98 | {0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b}, 99 | {0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4}, 100 | {0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f}, 101 | {0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef}, 102 | {0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61}, 103 | {0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}, 104 | }; 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/constant/DESConstants.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.constant; 2 | 3 | public interface DESConstants { 4 | 5 | // Permuted Choice 1 C0 6 | short[] PERMUTED_CHOICE_1_C0 = { 7 | 57, 49, 41, 33, 25, 17, 9, 8 | 1, 58, 50, 42, 34, 26, 18, 9 | 10, 2, 59, 51, 43, 35, 27, 10 | 19, 11, 3, 60, 52, 44, 36 11 | }; 12 | 13 | // Permuted Choice 1 D0 14 | short[] PERMUTED_CHOICE_1_D0 = { 15 | 63, 55, 47, 39, 31, 23, 15, 16 | 7, 62, 54, 46, 38, 30, 22, 17 | 14, 6, 61, 53, 45, 37, 29, 18 | 21, 13, 5, 28, 20, 12, 4 19 | }; 20 | 21 | // loop left shifting bits 22 | short[] moveBit = {1, 1, 2, 2, 2, 2, 2, 2, 23 | 1, 2, 2, 2, 2, 2, 2, 1}; 24 | 25 | // Replacement and Selection 2 26 | short[] replace2 = { 27 | 14, 17, 11, 24, 1, 5, 28 | 3, 28, 15, 6, 21, 10, 29 | 23, 19, 12, 4, 26, 8, 30 | 16, 7, 27, 20, 13, 2, 31 | 41, 52, 31, 37, 47, 55, 32 | 30, 40, 51, 45, 33, 48, 33 | 44, 49, 39, 56, 34, 53, 34 | 46, 42, 50, 36, 29, 32 35 | }; 36 | 37 | // initial permutation 38 | short[] IP = { 39 | 58, 50, 42, 34, 26, 18, 10, 2, 40 | 60, 52, 44, 36, 28, 20, 12, 4, 41 | 62, 54, 46, 38, 30, 22, 14, 6, 42 | 64, 56, 48, 40, 32, 24, 16, 8, 43 | 57, 49, 41, 33, 25, 17, 9, 1, 44 | 59, 51, 43, 35, 27, 19, 11, 3, 45 | 61, 53, 45, 37, 29, 21, 13, 5, 46 | 63, 55, 47, 39, 31, 23, 15, 7 47 | }; 48 | 49 | // selection and calculation E 50 | short[] E = { 51 | 32, 1, 2, 3, 4, 5, 52 | 4, 5, 6, 7, 8, 9, 53 | 8, 9, 10, 11, 12, 13, 54 | 12, 13, 14, 15, 16, 17, 55 | 16, 17, 18, 19, 20, 21, 56 | 20, 21, 22, 23, 24, 25, 57 | 24, 25, 26, 27, 28, 29, 58 | 28, 29, 30, 31, 32, 1 59 | }; 60 | 61 | 62 | // substitute box 63 | short[][][] SUBSTITUTE_BOX = { 64 | //SHA1Digest 65 | { 66 | {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, 67 | { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, 68 | { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, 69 | {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} 70 | }, 71 | //S2 72 | { 73 | {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, 74 | { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, 75 | { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, 76 | {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} 77 | }, 78 | //S3 79 | { 80 | {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, 81 | {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, 82 | {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, 83 | { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} 84 | }, 85 | //S4 86 | { 87 | { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, 88 | {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, 89 | {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, 90 | { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} 91 | }, 92 | //S5 93 | { 94 | { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, 95 | {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, 96 | { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, 97 | {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} 98 | }, 99 | //S6 100 | { 101 | {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, 102 | {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, 103 | { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, 104 | { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} 105 | }, 106 | //S7 107 | { 108 | { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, 109 | {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, 110 | { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, 111 | { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} 112 | }, 113 | //S8 114 | { 115 | {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, 116 | { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, 117 | { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, 118 | { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} 119 | } 120 | }; 121 | 122 | 123 | // replacement and calculation P 124 | short[] P = { 125 | 16, 7, 20, 21, 126 | 29, 12, 28, 17, 127 | 1, 15, 23, 26, 128 | 5, 18, 31, 10, 129 | 2, 8, 24, 14, 130 | 32, 27, 3, 9, 131 | 19, 13, 30, 6, 132 | 22, 11, 4, 25 133 | }; 134 | 135 | // inverse initial permutation IP^-1 136 | short[] inverseIP = { 137 | 40, 8, 48, 16, 56, 24, 64, 32, 138 | 39, 7, 47, 15, 55, 23, 63, 31, 139 | 38, 6, 46, 14, 54, 22, 62, 30, 140 | 37, 5, 45, 13, 53, 21, 61, 29, 141 | 36, 4, 44, 12, 52, 20, 60, 28, 142 | 35, 3, 43, 11, 51, 19, 59, 27, 143 | 34, 2, 42, 10, 50, 18, 58, 26, 144 | 33, 1, 41, 9, 49, 17, 57, 25 145 | }; 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/CipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | public interface CipherService { 6 | /** 7 | * encrypt plaintext with key 8 | * @param plaintext text to be encrypted 9 | * @param key key 10 | * @return encrypted text 11 | */ 12 | String encrypt(String plaintext, String key) throws UnsupportedEncodingException; 13 | 14 | /** 15 | * decrypt encrypted text with key 16 | * @param encryptedText encrypted text 17 | * @param key key 18 | * @return origin plaintext 19 | */ 20 | String decrypt(String encryptedText, String key) throws UnsupportedEncodingException; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/assymmetry/RSACipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.assymmetry; 2 | 3 | import lombok.Getter; 4 | 5 | import java.math.BigInteger; 6 | import java.security.SecureRandom; 7 | 8 | @Getter 9 | public class RSACipherService { 10 | private final static BigInteger one = new BigInteger("1"); 11 | private final static SecureRandom random = new SecureRandom(); 12 | 13 | private BigInteger privateKey; 14 | private BigInteger publicKey; 15 | private BigInteger modulus; 16 | 17 | // generate an N-bit (roughly) public and private key 18 | public RSACipherService(int N) { 19 | // 随机选取选取素数p,q 20 | BigInteger p = BigInteger.probablePrime(N / 2, random); 21 | BigInteger q = BigInteger.probablePrime(N / 2, random); 22 | // 计算欧拉函数值 23 | BigInteger phi = (p.subtract(one)).multiply(q.subtract(one)); 24 | 25 | modulus = p.multiply(q); 26 | // 在实际应用中公钥通常为2^16 + 1 27 | publicKey = new BigInteger("65537"); 28 | // 模逆运算 29 | privateKey = publicKey.modInverse(phi); 30 | } 31 | 32 | 33 | public BigInteger encrypt(BigInteger message) { 34 | return message.modPow(publicKey, modulus); 35 | } 36 | 37 | public BigInteger decrypt(BigInteger encrypted) { 38 | return encrypted.modPow(privateKey, modulus); 39 | } 40 | 41 | public String toString() { 42 | String s = ""; 43 | s += "public = " + publicKey + "\n"; 44 | s += "private = " + privateKey + "\n"; 45 | s += "modulus = " + modulus; 46 | return s; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/assymmetry/RawRSACipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.assymmetry; 2 | 3 | import lombok.Getter; 4 | import org.jordon.security.util.MathUtil; 5 | 6 | import java.util.Base64; 7 | import java.util.Random; 8 | import java.util.concurrent.ThreadLocalRandom; 9 | 10 | /** 11 | * 原生RSA加解密算法实现 12 | * @author Jrodon 13 | * @since 2018/10 14 | */ 15 | @Getter 16 | public class RawRSACipherService { 17 | // 密钥属性组 18 | private long n, d, e, eulerVal, p, q; 19 | // 素数的选择范围 20 | private static final int RANGE = 100; 21 | // 加密完得到的 22 | private static final int SPLIT_POINT = 2 << 8; 23 | // 素性测试轮数 24 | private static final int PRIMALITY_TESTING_ROUNDS = 4; 25 | // Base64编码工具 26 | private static final Base64.Encoder encoder = Base64.getEncoder(); 27 | private static final Base64.Decoder decoder = Base64.getDecoder(); 28 | 29 | public RawRSACipherService() { 30 | Random random = ThreadLocalRandom.current(); 31 | // 随机选择两个大素数 32 | long p = MathUtil.probablePrime(RANGE, PRIMALITY_TESTING_ROUNDS), q; 33 | do { 34 | q = MathUtil.probablePrime(RANGE, PRIMALITY_TESTING_ROUNDS); 35 | } while (p == q); 36 | 37 | long eulerVal = (p - 1) * (q - 1); 38 | 39 | // 随机地取一个正整数e,1 0) { 103 | int[] result = new int[chars.length]; 104 | for (int i = 0; i < chars.length; i++) { 105 | result[i] = chars[i]; 106 | } 107 | return result; 108 | } 109 | return null; 110 | } 111 | } -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/symmetry/AESCipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.symmetry; 2 | 3 | import org.jordon.security.constant.AESConstants; 4 | import org.jordon.security.core.crypto.CipherService; 5 | import org.jordon.security.util.ArrayUtil; 6 | import org.jordon.security.util.Base64Util; 7 | 8 | import static org.jordon.security.util.ArrayUtil.transferToShorts; 9 | 10 | public class AESCipherService implements CipherService { 11 | 12 | /** 13 | * 对外的解密接口 14 | * public decryption api 15 | * @param encryptedText encrypted text 16 | * @param key key 17 | * @return decrypted text 18 | */ 19 | @Override 20 | public String decrypt(String encryptedText, String key) { 21 | System.out.println("\n\n##################### decryption #####################"); 22 | ArrayUtil.printInfo("encrypted text", encryptedText, false); 23 | ArrayUtil.printInfo("key text", key, false); 24 | 25 | short[][] initialTextState = transfer(Base64Util.decodeToShorts(encryptedText)); 26 | short[][] initialKeyState = transfer(transferToShorts(key)); 27 | 28 | ArrayUtil.printInfo("initial encrypted state", getStateHex(initialTextState), false); 29 | ArrayUtil.printInfo("initial key state", getStateHex(initialKeyState), true); 30 | 31 | short[][] decryptState = coreDecrypt(initialTextState, initialKeyState); 32 | String plaintext = getOrigin(decryptState); 33 | ArrayUtil.printInfo("plaintext", plaintext, false); 34 | return plaintext; 35 | } 36 | 37 | /** 38 | * 将最终解密的short数组还原为字符串 39 | * transfer state into string 40 | * @param decryptState decrypt state 41 | * @return plaintext string 42 | */ 43 | private String getOrigin(short[][] decryptState) { 44 | StringBuilder builder = new StringBuilder(); 45 | for (short[] shorts : decryptState) { 46 | for (short s : shorts) { 47 | builder.append(String.valueOf((char) s)); 48 | } 49 | } 50 | return builder.toString(); 51 | } 52 | 53 | /** 54 | * 解密逻辑:通过将可逆操作抽取成可逆矩阵, 复用加密核心函数 55 | * @param encryptedTextState initial encrypted text state 56 | * @param keyState initial key state 57 | * @return decrypted state 58 | */ 59 | private short[][] coreDecrypt(short[][] encryptedTextState, short[][] keyState) { 60 | // obtain raw round keys 61 | short[][] rawRoundKeys = generateRoundKeys(keyState); 62 | System.out.println("RoundKeys"); 63 | printRoundKeys(rawRoundKeys); 64 | 65 | // make it easier to obtain a whole block of round key in a round transformation 66 | short[][][] roundKeys = transfer(rawRoundKeys); 67 | 68 | for (int i = 1; i < roundKeys.length - 1; i++) { 69 | roundKeys[i] = mixColumns(roundKeys[i], AESConstants.INVERSE_CX); 70 | } 71 | 72 | short[][][] inverseRoundKeys = inverseRoundKeys(roundKeys); 73 | System.out.println("inverse roundKeys"); 74 | printRoundKeys(inverseRoundKeys); 75 | return coreEncrypt(encryptedTextState, inverseRoundKeys, AESConstants. 76 | INVERSE_SUBSTITUTE_BOX, AESConstants.INVERSE_CX, AESConstants.INVERSE_SHIFTING_TABLE); 77 | } 78 | 79 | /** 80 | * [解密] 将解密扩展密钥数组逆转,方便复用核心加密操作, 81 | * @param roundKeys 解密扩展密钥数组 82 | * @return 逆转了的解密扩展密钥数组 83 | */ 84 | private short[][][] inverseRoundKeys(short[][][] roundKeys) { 85 | short[][][] result = new short[roundKeys.length][4][4]; 86 | int length = roundKeys.length; 87 | for (int i = 0; i < roundKeys.length; i++) { 88 | result[i] = roundKeys[length - 1 - i]; 89 | } 90 | return result; 91 | } 92 | 93 | /** 94 | * 对外的加密接口 95 | * public encryption api 96 | * @param plaintext text to be encrypted 97 | * @param key key 98 | * @return encryption result 99 | */ 100 | @Override 101 | public String encrypt(String plaintext, String key) { 102 | // transfer plaintext and key from one-dimension matrix 103 | // to (data.length / 4) x 4 matrix 104 | System.out.println("##################### encryption #####################"); 105 | ArrayUtil.printInfo("plaintext text", plaintext, false); 106 | ArrayUtil.printInfo("key text", key, false); 107 | short[][] initialPTState = transfer(transferToShorts(plaintext)); 108 | ArrayUtil.printInfo("initial plaintext state", getStateHex(initialPTState), false); 109 | short[][] initialKeyState = transfer(transferToShorts(key)); 110 | ArrayUtil.printInfo("initial key state", getStateHex(initialKeyState), true); 111 | 112 | // obtain raw round keys 113 | short[][] rawRoundKeys = generateRoundKeys(initialKeyState); 114 | System.out.println("RoundKeys"); 115 | printRoundKeys(rawRoundKeys); 116 | 117 | // make it easier to obtain a whole block of round key in a round transformation 118 | short[][][] roundKeys = transfer(rawRoundKeys); 119 | 120 | short[][] finalState = coreEncrypt(initialPTState, roundKeys, AESConstants.SUBSTITUTE_BOX, 121 | AESConstants.CX, AESConstants.SHIFTING_TABLE); 122 | return Base64Util.encode(transfer2Bytes(finalState)); 123 | } 124 | 125 | /** 126 | * AES核心操作,通过将可逆操作抽取成可逆矩阵作为参数,使该方法能在加/解密操作中复用 127 | * @param initialPTState 明文或密文的状态数组 128 | * @param roundKeys 加/解密要用到的轮密钥数组 129 | * @param substituteTable 加/解密要用到的S盒 130 | * @param mixColumnTable 列混合中用来取代既约多项式的数组 131 | * @param shiftingTable 行变换中用来决定字间左移的位数的数组 132 | * @return 加/解密结果 133 | */ 134 | private short[][] coreEncrypt(short[][] initialPTState, 135 | short[][][] roundKeys, short[][] substituteTable, 136 | short[][] mixColumnTable, short[][] shiftingTable) { 137 | 138 | // 初始轮密钥加,异或操作 139 | short[][] state = xor(roundKeys[0], initialPTState); 140 | 141 | // 处理前九轮变换 142 | for (int i = 0; i < 9; i++) { 143 | System.out.println("N = " + (i + 1)); 144 | // 将状态数组的字节替换为S盒中相应位置的字节 145 | state = substituteState(state, substituteTable); 146 | ArrayUtil.printInfo("SubBytes", getStateHex(state), false); 147 | 148 | // 行移位变换 149 | state = shiftRows(state, shiftingTable); 150 | ArrayUtil.printInfo("ShiftRows", getStateHex(state), false); 151 | 152 | // 列混合变换 153 | state = mixColumns(state, mixColumnTable); 154 | ArrayUtil.printInfo("MixColumns", getStateHex(state), false); 155 | 156 | // 轮密钥加变换 157 | ArrayUtil.printInfo("RoundKey", getStateHex(roundKeys[i + 1]), false); 158 | state = xor(roundKeys[i + 1], state); 159 | ArrayUtil.printInfo("AddRoundKeys", getStateHex(state), true); 160 | } 161 | 162 | // 处理最后一轮 163 | System.out.println("N = 10"); 164 | state = substituteState(state, substituteTable); 165 | ArrayUtil.printInfo("SubBytes", getStateHex(state), false); 166 | 167 | state = shiftRows(state, shiftingTable); 168 | ArrayUtil.printInfo("ShiftRows", getStateHex(state), false); 169 | 170 | ArrayUtil.printInfo("RoundKey", getStateHex(roundKeys[roundKeys.length - 1]), false); 171 | state = xor(roundKeys[roundKeys.length - 1], state); 172 | ArrayUtil.printInfo("AddRoundKeys", getStateHex(state), false); 173 | return state; 174 | } 175 | 176 | /** 177 | * 将加密后得到的状态数组转成字节数组,便于进行Base64编码 178 | * @param finalState 加密后得到的状态数组 179 | * @return 状态数组对应的字节数组 180 | */ 181 | private byte[] transfer2Bytes(short[][] finalState) { 182 | byte[] result = new byte[finalState.length * 4]; 183 | for (int i = 0;i < finalState.length; i++) { 184 | for (int j = 0; j < 4; j++) { 185 | result[i * 4 + j] = (byte) (finalState[i][j] & 0xff); 186 | } 187 | } 188 | return result; 189 | } 190 | 191 | /** 192 | * 列混合变换:状态数组与多项式等价矩阵进行有限域GF(2)上的矩阵乘法 193 | * @param state 状态数组 194 | * @param table 多项式等价矩阵 195 | * @return 列混合变换后的新状态 196 | */ 197 | private short[][] mixColumns(short[][] state, short[][] table) { 198 | short[][] result = new short[state.length][4]; 199 | for (int i = 0; i < state.length; i++) { 200 | result[i] = matrixMultiply(state[i], table); 201 | } 202 | return result; 203 | } 204 | 205 | /** 206 | * 一个字与多项式等价数组在有限域GF(2)上的乘法操作 207 | * multiplication between a word of a state and a irreducible 208 | * polynomial C(x)=03x^3+01x^2+01^2+01x+02 which is replaced as a 209 | * constant table AESConstants.CX 210 | * (aes-128: 4x4 x 4x1 = 4x1) 211 | * @param aWord a word of a state 212 | * @return multiplication result, a new word 213 | */ 214 | private short[] matrixMultiply(short[] aWord, short[][] table) { 215 | short[] result = new short[4]; 216 | for (int i = 0; i < 4; i++) { 217 | result[i] = wordMultiply(table[i], aWord); 218 | } 219 | return result; 220 | } 221 | 222 | /** 223 | * 两个字在有限域GF(2)上的乘法操作 224 | * multiplication between two words 225 | * @param firstWord first operand 226 | * @param secondWord second operand 227 | * @return multiplication result, a byte actually 228 | */ 229 | private short wordMultiply(short[] firstWord, short[] secondWord) { 230 | short result = 0; 231 | for (int i=0; i < 4; i++) { 232 | result ^= multiply(firstWord[i], secondWord[i]); 233 | } 234 | return result; 235 | } 236 | 237 | /** 238 | * 有限域GF(2)上的乘法操作,通过分解操作数将之转化成有限域GF(2)上的倍乘操作 239 | * multiplication in finite field GF(2^8) 240 | * @param a an operand of this kind of multiplication 241 | * @param b another operand of this kind of multiplication 242 | * @return multiplication result 243 | */ 244 | private short multiply(short a, short b) { 245 | short temp = 0; 246 | while (b != 0) { 247 | if ((b & 0x01) == 1) { 248 | temp ^= a; 249 | } 250 | a <<= 1; 251 | if ((a & 0x100) > 0) { 252 | /* 253 | judge if a is greater than 0x80, if then subtract a 254 | irreducible polynomial which can be substituted by 0x1b 255 | cause addition and subtraction are equivalent in this case 256 | it's okay to xor 0x1b 257 | */ 258 | a ^= 0x1b; 259 | } 260 | b >>= 1; 261 | } 262 | return (short) (temp & 0xff); 263 | } 264 | 265 | /** 266 | * 轮密钥扩展:将1个状态长度的主密钥扩展成rounds + 1个状态长度的轮密钥数组 267 | * generation of round keys 268 | * @param originalKey original cipher key 269 | * @return round keys 270 | */ 271 | private short[][] generateRoundKeys(short[][] originalKey) { 272 | short[][] roundKeys = new short[44][4]; 273 | int keyWordCount = originalKey.length; 274 | // 1. copy the original cipher words into the first four words of the roundKeys 275 | System.arraycopy(originalKey, 0, roundKeys, 0, keyWordCount); 276 | // 2. extension from previous word 277 | for (int i = keyWordCount; i < keyWordCount * 11; i++) { 278 | short[] temp = roundKeys[i - 1]; 279 | if (i % keyWordCount == 0) { 280 | temp = xor(substituteWord(leftShift(temp)), AESConstants.R_CON[i / keyWordCount]); 281 | } 282 | roundKeys[i] = xor(roundKeys[i - keyWordCount], temp); 283 | } 284 | return roundKeys; 285 | } 286 | 287 | /** 288 | * 状态替代:对状态中的每个字进行字替代 289 | * substitute value of a state array using byte as unit 290 | * @param state state array to be substituted 291 | * @return substitution result, a new state array 292 | */ 293 | private short[][] substituteState(short[][] state, short[][] substituteTable) { 294 | for (int i = 0; i < state.length; i++) { 295 | for (int j = 0; j < 4 ; j++) { 296 | state[i][j] = substituteByte(state[i][j], substituteTable); 297 | } 298 | } 299 | return state; 300 | } 301 | 302 | /** 303 | * 字替代:对字中每个字节进行字节替代 304 | * substitute all bytes in a word through SBox 305 | * @param aWord a word, aka 4 bytes 306 | * @return substitution result, a new and disrupted word 307 | */ 308 | private short[] substituteWord(short[] aWord) { 309 | for (int i = 0; i < 4; i++) { 310 | aWord[i] = substituteByte(aWord[i], AESConstants.SUBSTITUTE_BOX); 311 | } 312 | return aWord; 313 | } 314 | 315 | /** 316 | * 字节替代: 取一个字的高四位和低四位分别作为S盒的行号和列号, 317 | * 通过行列号取S盒中的字节替代原字节 318 | * substitute value of a byte through SBox 319 | * @param originalByte byte to be substituted 320 | * @return substitution result, a new byte 321 | */ 322 | private short substituteByte(short originalByte, short[][] substituteTable) { 323 | // low 4 bits in a originByte 324 | int low4Bits = originalByte & 0x000f; 325 | // high 4 bits in a originByte 326 | int high4Bits = (originalByte >> 4) & 0x000f; 327 | // obtain value in AESConstants.SUBSTITUTE_BOX 328 | return substituteTable[high4Bits][low4Bits]; 329 | } 330 | 331 | /** 332 | * 行移位变换:对状态的行进行循环左移,左移规则在shiftingTable中定义 333 | * row shifting operation, rotate over N which is defined in 334 | * AESConstants.SHIFTING_TABLE bytes of corresponding rows 335 | * @param state state array of the original plaintext 336 | * @return a new state array 337 | */ 338 | private static short[][] shiftRows(short[][] state, short[][] shiftingTable) { 339 | short[][] result = new short[state.length][4]; 340 | for (int j = 0; j < 4; j++) { // local byte in a word 341 | for (int i = 0; i < state.length; i++) { // local word 342 | result[i][j] = state[shiftingTable[i][j]][j]; 343 | } 344 | } 345 | return result; 346 | } 347 | 348 | /** 349 | * 以字节为单位循环左移1个单位, LEFT_SHIFT_TABLE 决定移动的规则 350 | * loop left shift a byte in a word, LEFT_SHIFT_TABLE decides how to move 351 | * @param aWord 操作字 352 | * @return 循环左移操作结果 353 | */ 354 | private short[] leftShift(short[] aWord) { 355 | short[] result = new short[4]; 356 | for (int i = 0; i < 4; i++) { 357 | result[i] = aWord[AESConstants.LEFT_SHIFT_TABLE[i]]; 358 | } 359 | return result; 360 | } 361 | 362 | /** 363 | * 将二维数组转成三维数组,方便在轮变换中通过轮下标获取 Nk x 4 的轮密钥矩阵 364 | * make it easier to process several specific blocks of the origin arrays 365 | * @param origin 二维轮密钥数组 366 | * @return 三维轮密钥数组 367 | */ 368 | private short[][][] transfer(short[][] origin) { 369 | short[][][] result = new short[origin.length / 4][4][4]; 370 | for (int i = 0; i < origin.length / 4; i++) { 371 | short[][] temp = new short[4][4]; 372 | System.arraycopy(origin, i * 4, temp, 0, 4); 373 | result[i] = temp; 374 | } 375 | return result; 376 | } 377 | 378 | /** 379 | * 将1 x modeSize矩阵转成Nb x 4状态矩阵,通常用在获取明文和密钥的初始状态数组 380 | * transfer short[] to short[][], usually return an initial state 381 | * @param origin origin array short[] 382 | * @return transferred array 383 | */ 384 | private short[][] transfer(short[] origin) { 385 | short[][] result = new short[origin.length / 4][4]; 386 | for (int i = 0; i < result.length; i++) { 387 | System.arraycopy(origin, i * 4, result[i], 0, 4); 388 | } 389 | return result; 390 | } 391 | 392 | /** 393 | * 有限域GF(2)上的加法,modeSize位的异或操作 394 | * xor corresponding byte in two state arrays 395 | * @param first first operand 396 | * @param second second operand 397 | * @return xor result 398 | */ 399 | private short[][] xor(short[][] first, short[][] second) { 400 | short[][] result = new short[first.length][4]; 401 | int length = first.length; 402 | for (short i = 0; i < length; i++) { 403 | for (short j = 0; j < length; j++) { 404 | result[i][j] = (short) (first[i][j] ^ second[i][j]); 405 | } 406 | } 407 | return result; 408 | } 409 | 410 | /** 411 | * 两个字间的异或操作 412 | * xor corresponding byte in two words 413 | * @param first first operand 414 | * @param second second operand 415 | * @return xor result 416 | */ 417 | private short[] xor(short[] first, short[] second) { 418 | short[] result = new short[4]; 419 | for (short i = 0; i < 4; i++) { 420 | result[i] = (short) (first[i] ^ second[i]); 421 | } 422 | return result; 423 | } 424 | 425 | /** 426 | * 状态数组的十六进制串 427 | * obtain state array 428 | * @param state a state 429 | * @return hex string of state 430 | */ 431 | private String getStateHex(short[][] state) { 432 | StringBuilder builder = new StringBuilder(); 433 | for (short[] aWord : state) { 434 | builder.append(toHexString(aWord)); 435 | } 436 | return builder.toString(); 437 | } 438 | 439 | /** 440 | * 打印轮密钥数组 441 | * print round keys 442 | * @param roundKeys round keys 443 | */ 444 | private void printRoundKeys(short[][] roundKeys) { 445 | for (int i = 0, keyOrder = 1; i < roundKeys.length; i += 4, keyOrder++) { 446 | String infoKValue = getStateHex(new short[][]{ 447 | roundKeys[i], roundKeys[i + 1], 448 | roundKeys[i + 2], roundKeys[i + 3] 449 | }); 450 | ArrayUtil.printInfo("[RoundKey " + keyOrder + "]", infoKValue, false); 451 | } 452 | System.out.println(); 453 | } 454 | 455 | /** 456 | * 打印三维轮密钥数组 457 | * @param roundKeys round keys 458 | */ 459 | private void printRoundKeys(short[][][] roundKeys) { 460 | for (int i = 0; i < roundKeys.length; i++) { 461 | String infoKValue = getStateHex(roundKeys[i]); 462 | ArrayUtil.printInfo("[RoundKey " + (i + 1) + "]", infoKValue, false); 463 | } 464 | System.out.println(); 465 | } 466 | 467 | /** 468 | * 将一个字以字节为单位转换成十六进制形式字符串 469 | * format a word in hexadecimal string 470 | * @param aWord a word 471 | * @return hex string of a word 472 | */ 473 | private String toHexString(short[] aWord) { 474 | StringBuilder builder = new StringBuilder(); 475 | for (short aByte : aWord) { 476 | builder.append(toHexString(aByte)); 477 | } 478 | return builder.toString(); 479 | } 480 | 481 | /** 482 | * 获取一个字节的十六进制串 483 | * @param value a byte 484 | * @return hex string of a byte 485 | */ 486 | private String toHexString(short value) { 487 | String hexString = Integer.toHexString(value); 488 | if (hexString.toCharArray().length == 1) { 489 | hexString = "0" + hexString; 490 | } 491 | return hexString; 492 | } 493 | } 494 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/symmetry/DESCipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.symmetry; 2 | 3 | import org.jordon.security.constant.DESConstants; 4 | import org.jordon.security.core.crypto.CipherService; 5 | import org.jordon.security.util.ArrayUtil; 6 | import org.jordon.security.util.Base64Util; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.UnsupportedEncodingException; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Random; 15 | 16 | public class DESCipherService implements CipherService { 17 | 18 | private boolean printMsg; 19 | private List messages; 20 | private String workingMode; 21 | private char[] IV; 22 | private char[][] counters; 23 | 24 | public List getMessages() { 25 | return messages; 26 | } 27 | 28 | public void clearMessages() { 29 | messages.clear(); 30 | } 31 | 32 | public DESCipherService(boolean printMsg) { 33 | this.printMsg = printMsg; 34 | this.messages = new ArrayList<>(); 35 | } 36 | 37 | public void setWorkingMode(String workingMode) { 38 | this.workingMode = workingMode; 39 | } 40 | 41 | /** 42 | * 明文填充,最后一组的最后8位表示填充长度 43 | */ 44 | public char[][] padPlaintext(char[] plaintextBytes) { 45 | 46 | System.out.println("填充前的比特串: " + String.valueOf(plaintextBytes)); 47 | int length = plaintextBytes.length; 48 | int lastBlockBits = length % 64; 49 | // 现有块数 50 | int blockCount = length / 64; 51 | 52 | // 待伪随机填充位数 53 | int randPadCount = 64 - lastBlockBits - 8; 54 | char[] padded = new char[(blockCount + 1) * 64]; 55 | System.arraycopy(plaintextBytes, 0, padded, 0, length); 56 | 57 | // 伪随机填充 58 | for (int i = length; i < padded.length - 8; i++) { 59 | padded[i] = new Random().nextBoolean() ? '1' : '0'; 60 | } 61 | // 填充最后一个字节比特串 62 | char[] padCountVal = Integer.toBinaryString( 63 | (randPadCount & 0xff) + 0x0100).substring(1).toCharArray(); 64 | System.arraycopy(padCountVal, 0, padded, padded.length - 8, 8); 65 | 66 | System.out.println("填充后的比特串: " + String.valueOf(padded)); 67 | 68 | // 将填充完比特穿分组 69 | char[][] blocks = new char[blockCount + 1][64]; 70 | for (int i = 0; i < blockCount + 1; i++) { 71 | System.arraycopy(padded, i * 64, blocks[i], 0, 64); 72 | } 73 | return blocks; 74 | } 75 | 76 | 77 | /** 78 | * encrypt plaintext with key 79 | * @param plaintext text to be encrypted 80 | * @param key key 81 | * @return encrypted text 82 | * @throws UnsupportedEncodingException caused by String.getBytes() 83 | */ 84 | @Override 85 | public String encrypt(String plaintext, String key) throws UnsupportedEncodingException { 86 | if (printMsg) { 87 | messages.add(ArrayUtil.printInfo("plaintext", plaintext, false)); 88 | messages.add(ArrayUtil.printInfo("keyText", key, true)); 89 | } 90 | char[] keyBytes = ArrayUtil.bytesToChars(key.getBytes("UTF-8")); 91 | // 获取填充后的所有分组 92 | 93 | char[] plaintextBytes = ArrayUtil.bytesToChars(plaintext.getBytes()); 94 | return encrypt(plaintextBytes, keyBytes); 95 | } 96 | 97 | /** 98 | * 对文件进行加密 99 | * @param file 文件 100 | * @param key 密钥 101 | * @return 加密结果 102 | */ 103 | public String encryptFile(File file, String key) throws UnsupportedEncodingException, FileNotFoundException { 104 | if (printMsg) { 105 | messages.add(ArrayUtil.printInfo("fileName", file.getName(), false)); 106 | messages.add(ArrayUtil.printInfo("keyText", key, true)); 107 | } 108 | char[] keyBytes = ArrayUtil.bytesToChars(key.getBytes("UTF-8")); 109 | // 获取填充后的所有分组 110 | char[] plaintextBytes = ArrayUtil.bytesToChars(ArrayUtil.getBytes(file)); 111 | return encrypt(plaintextBytes, keyBytes); 112 | } 113 | 114 | public String encrypt(char[] plaintextBytes, char[] keyBytes) { 115 | // 填充、分组 116 | char[][] blocks = padPlaintext(plaintextBytes); 117 | 118 | int blockCount = blocks.length; 119 | char[] cipherVal = new char[blocks.length * 64]; 120 | 121 | switch (workingMode) { 122 | case "ECB": 123 | // 对一块进行加密 124 | for (int i = 0; i < blockCount; i++) { 125 | char[] aCipher = encryptABlock(blocks[i], keyBytes); 126 | System.arraycopy(aCipher, 0, cipherVal, i * 64, 64); 127 | } 128 | break; 129 | 130 | case "CBC": 131 | // 初始向量IV 132 | char[] IV = ranBlock(); 133 | this.IV = IV; 134 | char[] input; 135 | for (int i = 0; i < blocks.length; i++) { 136 | input = ArrayUtil.xor(IV, blocks[i], 64); 137 | char[] aCipher = encryptABlock(input, keyBytes); 138 | IV = aCipher; 139 | System.arraycopy(aCipher, 0, cipherVal, i * 64, 64); 140 | } 141 | break; 142 | 143 | case "CTR": 144 | // 初始化blockCount个计数器 145 | counters = new char[blockCount][64]; 146 | for (int i = 0; i < blockCount; i++) { 147 | counters[i] = ranBlock(); 148 | } 149 | // 加密过程 150 | for (int i = 0; i < blocks.length; i++) { 151 | char[] aCipher = ArrayUtil.xor(blocks[i], encryptABlock(counters[i], keyBytes), 64); 152 | System.arraycopy(aCipher, 0, cipherVal, i * 64, 64); 153 | } 154 | break; 155 | } 156 | if (printMsg) { 157 | messages.add(ArrayUtil.printBitChars("cipher blocks bits", cipherVal)); 158 | } 159 | ArrayUtil.printBitChars("cipherVal", cipherVal); 160 | return Base64Util.encode(cipherVal); 161 | } 162 | 163 | /** 164 | * 产生随机64位比特串 165 | * @return 64位比特串 166 | */ 167 | private char[] ranBlock() { 168 | char[] result = new char[64]; 169 | for (int i = 0; i < 64; i++) { 170 | result[i] = new Random().nextBoolean() ? '1' : '0'; 171 | } 172 | return result; 173 | } 174 | 175 | /** 176 | * 单块加密 177 | * @param plaintextBytes 明文分组(64位) 178 | * @param keyBytes 密钥串 179 | * @return 加密结果 180 | */ 181 | private char[] encryptABlock(char[] plaintextBytes, char[] keyBytes) { 182 | if (printMsg) { 183 | messages.add(ArrayUtil.printBitChars("plaintext bits", plaintextBytes)); 184 | messages.add(ArrayUtil.printBitChars("key bits", keyBytes)); 185 | } 186 | 187 | char[][] subKeys = generateSubKeys(keyBytes); 188 | char[] result = encode(plaintextBytes, subKeys); 189 | 190 | if (printMsg) { 191 | messages.add(ArrayUtil.printBitChars("encryptedText bits", result)); 192 | } 193 | return result; 194 | } 195 | 196 | /** 197 | * main encryption logic 198 | * @param plaintextBytes plaintext bits in chars format 199 | * @param subKeys subKeys bits in chars format 200 | * @return encryption result bits in chars format 201 | */ 202 | public char[] encode(char[] plaintextBytes, char[][] subKeys) { 203 | System.out.println(plaintextBytes.length); 204 | // initial permutation, get 64 bit disrupted array 205 | char[] chars = ArrayUtil.disruptArray(plaintextBytes, DESConstants.IP); 206 | if (printMsg) { 207 | ArrayUtil.printBitChars("plaintext after ip", chars); 208 | } 209 | 210 | int length = chars.length; 211 | String binaryArrayStr = String.valueOf(chars); 212 | char[] left = binaryArrayStr.substring(0, length / 2).toCharArray(); 213 | char[] right = binaryArrayStr.substring(length / 2).toCharArray(); 214 | char[] coreEncrypted, xorResult; 215 | 216 | if (printMsg) { 217 | messages.add(ArrayUtil.printBitChars("L0", left)); 218 | messages.add(ArrayUtil.printBitChars("R0", right)); 219 | } 220 | 221 | for (int i = 0; i < 16; i++) { 222 | if (printMsg) { 223 | System.out.println(); 224 | messages.add("\n"); 225 | } 226 | 227 | coreEncrypted = coreEncrypt(right, subKeys[i]); 228 | 229 | if (printMsg) { 230 | messages.add(ArrayUtil.printBitChars("[f] " + 231 | "P Replacement", coreEncrypted)); 232 | } 233 | // get 32-bit array 234 | xorResult = String.valueOf(ArrayUtil.xor(left, coreEncrypted, 48)) 235 | .substring(16).toCharArray(); 236 | 237 | left = right; 238 | right = xorResult; 239 | 240 | if (printMsg){ 241 | messages.add(ArrayUtil.printBitChars("[" + (i + 1) + "] " + "left", left)); 242 | messages.add(ArrayUtil.printBitChars("[" + (i + 1) + "] " + "right", right)); 243 | } 244 | } 245 | if (printMsg) { 246 | messages.add("\n"); 247 | System.out.println(); 248 | } 249 | char[] calResult = ArrayUtil.concat(right, left); 250 | return ArrayUtil.disruptArray(calResult, DESConstants.inverseIP); 251 | } 252 | 253 | /** 254 | * decrypt encrypted text with key 255 | * @param encryptedText encrypted text 256 | * @param key key 257 | * @return decrypted origin plaintext 258 | * @throws UnsupportedEncodingException caused by String.getBytes() 259 | */ 260 | @Override 261 | public String decrypt(String encryptedText, String key) throws UnsupportedEncodingException { 262 | if (printMsg) { 263 | messages.add(ArrayUtil.printInfo("encryptedText", encryptedText, false)); 264 | messages.add(ArrayUtil.printInfo("key", key, true)); 265 | } 266 | 267 | // 密文串 268 | char[] encryptedTextBytes = Base64Util.decodeToChars(encryptedText); 269 | // 密文分组 270 | char[][] cipherBlocks = new char[encryptedTextBytes.length / 64][64]; 271 | 272 | char[] keyBytes = ArrayUtil.bytesToChars(key.getBytes("UTF-8")); 273 | char[] decryptBytes = new char[cipherBlocks.length * 64]; 274 | 275 | // 处理工作模式 276 | switch (workingMode) { 277 | case "ECB": 278 | for (int i = 0; i < cipherBlocks.length; i++) { 279 | // 将密文串分组 280 | System.arraycopy(encryptedTextBytes, i * 64, cipherBlocks[i], 0, 64); 281 | // 单块解密 282 | char[] aBlockResult = decryptABlock(cipherBlocks[i], keyBytes); 283 | // 解密结果串成一串 284 | System.arraycopy(aBlockResult, 0, decryptBytes, i * 64, 64); 285 | } 286 | break; 287 | 288 | case "CBC": 289 | char[] input = IV; 290 | for (int i = 0; i < cipherBlocks.length; i++) { 291 | // 将密文串分组 292 | System.arraycopy(encryptedTextBytes, i * 64, cipherBlocks[i], 0, 64); 293 | // 单块解密 294 | char[] aBlockResult = ArrayUtil.xor(input, decryptABlock(cipherBlocks[i], keyBytes), 64); 295 | // 下一个异或输入为当前密文块 296 | input = cipherBlocks[i]; 297 | // 解密结果串成一串 298 | System.arraycopy(aBlockResult, 0, decryptBytes, i * 64, 64); 299 | } 300 | break; 301 | 302 | case "CTR": 303 | for (int i = 0; i < cipherBlocks.length; i++) { 304 | System.arraycopy(encryptedTextBytes, i * 64, cipherBlocks[i], 0, 64); 305 | char[] aBlockResult = ArrayUtil.xor(cipherBlocks[i], encryptABlock(counters[i], keyBytes), 64); 306 | // 解密结果串成一串 307 | System.arraycopy(aBlockResult, 0, decryptBytes, i * 64, 64); 308 | } 309 | break; 310 | } 311 | 312 | // 处理填充 313 | // 1. 抽出最后一个字节 314 | String decryptBytesStr = String.valueOf(decryptBytes); 315 | int paddedBits = Integer.parseInt(decryptBytesStr.substring(decryptBytes.length - 8), 2); 316 | System.out.println("pad " + paddedBits); 317 | char[] origin = decryptBytesStr.substring(0, decryptBytes.length - 8 - paddedBits).toCharArray(); 318 | String plaintext = ArrayUtil.segmentAndPrintChars(origin); 319 | // 2. 去掉填充信息 320 | if (printMsg) { 321 | messages.add(ArrayUtil.printBitChars("plaintext bits", origin)); 322 | messages.add(ArrayUtil.printInfo("plaintext", plaintext, false)); 323 | } 324 | return plaintext; 325 | } 326 | 327 | private char[] decryptABlock(char[] encryptedTextBlock, char[] keyBytes) { 328 | char[][] inverseKeys = inverseSubKeys(generateSubKeys(keyBytes)); 329 | char[] result = encode(encryptedTextBlock, inverseKeys); 330 | 331 | if (printMsg) { 332 | messages.add(ArrayUtil.printBitChars("encryptedBlock bits", encryptedTextBlock)); 333 | messages.add(ArrayUtil.printBitChars("key bits", keyBytes)); 334 | messages.add(ArrayUtil.printBitChars("decryptedText bits", result)); 335 | } 336 | return result; 337 | } 338 | 339 | /** 340 | * change over the sub keys for reusing the encode function 341 | * @param subKeys origin subKeys 342 | * @return inverse subKeys 343 | */ 344 | private char[][] inverseSubKeys(char[][] subKeys) { 345 | char[][] inverseKeys = new char[subKeys.length][]; 346 | 347 | for (int i = 0; i < subKeys.length; i++) { 348 | inverseKeys[i] = subKeys[subKeys.length - 1 - i]; 349 | } 350 | return inverseKeys; 351 | } 352 | 353 | /** 354 | * core function of DES, 355 | * disruption and confusion most because of 356 | * substituting and selecting operation 357 | * @param right the right split of plaintext of xor result of last calculation 358 | * @param subKey subKey in round i 359 | * @return result after P Replacement 360 | */ 361 | private char[] coreEncrypt(char[] right, char[] subKey) { 362 | // 1. do selection for 32-bit right disrupted info 363 | // get 48-bit extended array 364 | if (printMsg) { 365 | messages.add(ArrayUtil.printBitChars("[f] 32-bit input", right)); 366 | } 367 | char[] extendedRight = ArrayUtil.disruptArray(right, DESConstants.E); 368 | 369 | if (printMsg) { 370 | messages.add(ArrayUtil.printBitChars("[f] Selection", extendedRight)); 371 | messages.add(ArrayUtil.printBitChars("[f] subKey", subKey)); 372 | } 373 | 374 | // 2. xor 48-bit extendedRight and 48-bit subKey 375 | char[] xorResult = ArrayUtil.xor(extendedRight, subKey, 48); 376 | if (printMsg) { 377 | messages.add(ArrayUtil.printBitChars("[f] xor", xorResult)); 378 | } 379 | 380 | // 3. substitute box mixing and confusing 381 | // (1) format 1x48 matrix into an 8x6 matrix 382 | char[][] twoDimensionArray = ArrayUtil.segmentDimension(xorResult, 8, 6); 383 | StringBuilder outputBuilder = new StringBuilder(); 384 | for (int i = 0; i < twoDimensionArray.length; i++) { 385 | 386 | char[] rowBits = { 387 | twoDimensionArray[i][0], 388 | twoDimensionArray[i][5] 389 | }; 390 | char[] columnBits = { 391 | twoDimensionArray[i][1], twoDimensionArray[i][2], 392 | twoDimensionArray[i][3], twoDimensionArray[i][4] 393 | }; 394 | 395 | // (2) obtain the index of output value in SUBSTITUTE_BOX[i] 396 | int rowIndex = Integer.parseInt(String.valueOf(rowBits), 2); 397 | int columnIndex = Integer.parseInt(String.valueOf(columnBits), 2); 398 | // (3) obtain output of Si 399 | short output = DESConstants.SUBSTITUTE_BOX[i][rowIndex][columnIndex]; 400 | outputBuilder.append(Integer.toBinaryString((output & 0x0f) + 0x10).substring(1)); 401 | } 402 | char[] substitutedResult = outputBuilder.toString().toCharArray(); 403 | 404 | if (printMsg) { 405 | messages.add(ArrayUtil.printBitChars("[F] SBox", substitutedResult)); 406 | } 407 | 408 | // 4. replacement P, returns 28-bit array 409 | return ArrayUtil.disruptArray(substitutedResult, DESConstants.P); 410 | } 411 | 412 | /** 413 | * generate 16 48-bit sub keys 414 | * @param keyBytes origin key bits in chars format 415 | * @return 16-elements subKey array 416 | */ 417 | public char[][] generateSubKeys(char[] keyBytes) { 418 | char[][] subKeys = new char[16][48]; 419 | // Replacement and selection 1 420 | char[] c = ArrayUtil.disruptArray(keyBytes, DESConstants.PERMUTED_CHOICE_1_C0); 421 | 422 | if (printMsg) { 423 | messages.add(ArrayUtil.printBitChars("Permuted Choice 1 C0", c)); 424 | } 425 | 426 | char[] d = ArrayUtil.disruptArray(keyBytes, DESConstants.PERMUTED_CHOICE_1_D0); 427 | 428 | if (printMsg) { 429 | messages.add(ArrayUtil.printBitChars("Permuted Choice 1 D0", d)); 430 | messages.add("\nStart to generate sub keys......"); 431 | System.out.println("\nStart to generate sub keys......"); 432 | } 433 | 434 | // loop left shifting 435 | for (int i = 0; i < 16; i++) { 436 | c = ArrayUtil.leftShift(c, DESConstants.moveBit[i]); 437 | d = ArrayUtil.leftShift(d, DESConstants.moveBit[i]); 438 | 439 | if (printMsg) { 440 | messages.add(ArrayUtil.printBitChars("[" + (i + 1) + "]" + " leftShifting C", c)); 441 | messages.add(ArrayUtil.printBitChars("[" + (i + 1) + "]" + " leftShifting D", d)); 442 | } 443 | 444 | // 56 bit concat 445 | char[] concatChars = ArrayUtil.concat(c, d); 446 | if (printMsg) { 447 | messages.add(ArrayUtil.printBitChars("[" + (i + 1) + "]" + " concatChars", concatChars)); 448 | } 449 | 450 | // Replacement and selection 2, get 48 bit array 451 | char[] key = ArrayUtil.disruptArray(concatChars, DESConstants.replace2); 452 | subKeys[i] = key; 453 | if (printMsg) { 454 | String prefix = "[" + (i + 1) + "] subKey"; 455 | messages.add(ArrayUtil.printBitChars(prefix, key)); 456 | messages.add("\n"); 457 | System.out.println(); 458 | } 459 | } 460 | return subKeys; 461 | } 462 | } 463 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/crypto/symmetry/RC4CipherService.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.symmetry; 2 | 3 | import org.jordon.security.core.crypto.CipherService; 4 | import org.jordon.security.util.Base64Util; 5 | 6 | public class RC4CipherService implements CipherService { 7 | 8 | @Override 9 | public String encrypt(String plaintext, String key) { 10 | String raw = core(plaintext, key); 11 | return Base64Util.encode(raw); 12 | } 13 | 14 | @Override 15 | public String decrypt(String encryptedText, String key) { 16 | String raw = Base64Util.decode(encryptedText); 17 | return core(raw, key); 18 | } 19 | 20 | /** 21 | * RC4主要逻辑 22 | * 1. 初始化状态向量 23 | * 2. 获取流密钥 24 | * 3. 加/解密 25 | * @param text 明文或密文 26 | * @param key 密钥 27 | * @return 加/解密结果 28 | */ 29 | private String core(String text, String key) { 30 | // 状态向量 31 | int[] state = new int[256]; 32 | 33 | // 生成的密钥流 34 | char[] keySchedule = new char[text.length()]; 35 | 36 | StringBuilder cipherText = new StringBuilder(); 37 | 38 | scheduleKey(state, key); 39 | genPseudoRandom(state, keySchedule, text.length()); 40 | 41 | // 将密钥与明文/密文异或 42 | for (int i = 0; i < text.length(); i++) { 43 | cipherText.append((char) (text.charAt(i) ^ keySchedule[i])); 44 | } 45 | return cipherText.toString(); 46 | } 47 | 48 | /** 49 | * 初始化向量(Key-scheduling algorithm) 50 | * @param state 状态向量 51 | * @param key 密钥 52 | */ 53 | private void scheduleKey(int[] state, String key) { 54 | for (int i = 0; i < 256; i++) { 55 | state[i] = i; 56 | } 57 | for (int j = 0, i = 0; i < 256; i++) { 58 | j = (j + state[i] + key.charAt(i % key.length())) % 256; 59 | swap(state, i, j); 60 | } 61 | } 62 | 63 | /** 64 | * 伪随机生成算法(Pseudo-random generation algorithm) 65 | * @param state 状态向量 66 | * @param keySchedule 流密钥 67 | * @param plaintextLength 明文长度 68 | */ 69 | private void genPseudoRandom(int[] state, char[] keySchedule, int plaintextLength) { 70 | for (int i = 0, j = 0, k = 0; k < plaintextLength; k++) { 71 | i = (i + 1) % 256; 72 | j = (j + state[i]) % 256; 73 | swap(state, i, j); 74 | keySchedule[k] = (char) (state[(state[i] + state[j]) % 256]); 75 | } 76 | } 77 | 78 | /** 79 | * 交换数组s中第i和第j个元素 80 | * @param s 数组 81 | * @param i 待处理数索引 82 | * @param j 待处理数索引 83 | */ 84 | private void swap(int[] s, int i, int j) { 85 | int temp = s[i]; 86 | s[i] = s[j]; 87 | s[j] = temp; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/hash/IHash.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.hash; 2 | 3 | public interface IHash { 4 | byte[] hash(byte[] data); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/hash/SHA1.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.hash; 2 | 3 | import org.jordon.security.util.ArrayUtil; 4 | 5 | public class SHA1 { 6 | 7 | public void core() { 8 | 9 | } 10 | 11 | // 处理512位 12 | private void processABlock(byte[] data) { 13 | // 获取原始信息字节数 14 | int origMsgLen = data.length; 15 | // 获取原始信息总位数 16 | long origBitCount = origMsgLen * 8; 17 | 18 | // 末尾填充1 19 | byte[] appendOneMsg = new byte[origMsgLen + 1]; 20 | // 复制数据 21 | System.arraycopy(data, 0, appendOneMsg, 0, origMsgLen); 22 | // Java没法定义位,所以追加1操作是先追加字节,将字节最高位设为1 23 | appendOneMsg[appendOneMsg.length - 1] = (byte) 0x80; //append 1 24 | int apdOneMsgLen = appendOneMsg.length * 8; //get new length in bits 25 | 26 | // 确定需要添加0的位数,空出填充信息最后一块的最后64位 27 | while (apdOneMsgLen % 512 != 448) { 28 | apdOneMsgLen += 8; 29 | } 30 | // 填充0 31 | byte[] appendZerosMsg = new byte[apdOneMsgLen / 8]; 32 | System.arraycopy(appendOneMsg, 0 , appendZerosMsg, 0, appendOneMsg.length); 33 | 34 | // add 64 bits for original length 35 | // 根据消息初始长度追加64位 36 | byte[] output = new byte[appendZerosMsg.length + 8]; 37 | for (int i = 0; i < 8; i++) { 38 | output[output.length - 1 - i] = (byte)((origBitCount >>> (8 * i)) & 0xFF); 39 | } 40 | } 41 | 42 | /** 43 | * 将字节数组转成字数组(字长可变) 44 | * @param bytes 字节数组 45 | * @param wordLength 字长 46 | * @return 字数组 47 | */ 48 | private byte[][] bytes2Words(byte[] bytes, int wordLength) { 49 | if (wordLength > 0) { 50 | byte[][] words = new byte[bytes.length / wordLength][wordLength]; 51 | for (int i = 0, j = 0; i < bytes.length; i += wordLength, j++) { 52 | System.arraycopy(bytes, i, words[j], 0, wordLength); 53 | } 54 | return words; 55 | } 56 | return null; 57 | } 58 | 59 | /** 60 | * 字间异或 61 | * @param words 1,...,n个字 62 | * @return 异或结果 63 | */ 64 | private byte[] xor(byte[]... words) { 65 | byte[] result = new byte[4]; 66 | for (byte[] aWord : words) { 67 | for (int i = 0; i < 4; i++) { 68 | result[i] ^= aWord[i]; 69 | } 70 | } 71 | return result; 72 | } 73 | 74 | /** 75 | * 字节数组中比特循环左移 76 | * @param bytes 字节数组 77 | * @param bits 循环左移位数 78 | * @return 循环左移结果 79 | */ 80 | private byte[] leftRotate(byte[] bytes, int bits) { 81 | if (bits > 0) { 82 | StringBuilder builder = new StringBuilder(); 83 | for (byte aByte : bytes) { 84 | builder.append(Integer.toBinaryString(aByte & 0xff)); 85 | } 86 | String bitsStr = builder.toString(); 87 | String rotatedStr = bitsStr.substring(bits, bitsStr.length()) + 88 | bitsStr.substring(0, bits); 89 | return ArrayUtil.int2Bytes(Integer.parseInt(rotatedStr, 2)); 90 | } 91 | return null; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/hash/SHA1Digest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.hash; 2 | 3 | import org.jordon.security.util.Base64Util; 4 | 5 | public class SHA1Digest implements IHash { 6 | 7 | @Override 8 | public byte[] hash(byte[] data) { 9 | return new byte[0]; 10 | } 11 | 12 | public static void main(String[] args) { 13 | System.out.println(Base64Util.encode(encode(new byte[32]))); 14 | } 15 | 16 | /* 17 | * Encode ASCII formatted string using secure hash algorithm 18 | * @params data byte array of string to be encoded 19 | */ 20 | private static byte[] encode(byte[] data) { 21 | // pad byte array, assume ASCII encoding 22 | // 获取原始信息字节数 23 | int origMsgLen = data.length; // length in bytes 24 | // 获取原始信息总位数 25 | long origBitCount = origMsgLen * 8; // length in bits 26 | 27 | // 末尾填充1 28 | byte[] appendOneMsg = new byte[origMsgLen + 1]; 29 | // 复制数据 30 | System.arraycopy(data, 0, appendOneMsg, 0, origMsgLen); 31 | // Java没法操作,所以追加1操作是先追加字节,将字节最高位设为1 32 | appendOneMsg[appendOneMsg.length - 1] = (byte) 0x80; //append 1 33 | int apdOneMsgLen = appendOneMsg.length * 8; //get new length in bits 34 | 35 | // find length multiple of 512 36 | // 空出填充信息最后一块的最后64位 37 | while (apdOneMsgLen % 512 != 448) { 38 | apdOneMsgLen += 8; 39 | } 40 | 41 | // size of block with appended zeros 42 | // 填充0 43 | byte[] appendZerosMsg = new byte[apdOneMsgLen / 8]; 44 | System.arraycopy(appendOneMsg, 0 , appendZerosMsg, 0, appendOneMsg.length); 45 | 46 | // add 64 bits for original length 47 | // 根据消息初始长度追加64位 48 | byte[] output = new byte[appendZerosMsg.length + 8]; 49 | 50 | for (int i = 0; i < 8; i++) { 51 | output[output.length - 1 - i] = (byte)((origBitCount >>> (8 * i)) & 0xFF); 52 | } 53 | System.arraycopy(appendZerosMsg, 0 , output, 0, appendZerosMsg.length); 54 | 55 | int size = output.length; 56 | int num_chunks = size * 8 / 512; 57 | 58 | int h0 = 0x67452301; 59 | int h1 = 0xEFCDAB89; 60 | int h2 = 0x98BADCFE; 61 | int h3 = 0x10325476; 62 | int h4 = 0xC3D2E1F0; 63 | 64 | // hash each successive 512 chunk 65 | for (int i = 0; i < num_chunks; i++) { 66 | int[] w = new int[80]; 67 | // divide into 16 32 bit words 68 | // 将512位的明文分组划分为16个子明文分组,每个子明文分组为32位 69 | for (int j = 0; j < 16; j++) { 70 | w[j] = ((output[i * 512 / 8 + 4*j] << 24) & 0xFF000000) | 71 | ((output[i*512/8 + 4*j+1] << 16) & 0x00FF0000); 72 | w[j] |= ((output[i * 512 / 8 + 4 * j + 2] << 8) & 0xFF00) | 73 | (output[i*512/8 + 4*j+3] & 0xFF); 74 | } 75 | 76 | // extend 16 words into 80 words 77 | // 16份子明文分组扩展为80份。 78 | for (int j = 16; j < 80; j++) { 79 | w[j] = left_rotate(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); 80 | } 81 | 82 | // initialize initial values 83 | // 申请5个32位的链接变量,记为A、B、C、D、E。 84 | int a = h0; 85 | int b = h1; 86 | int c = h2; 87 | int d = h3; 88 | int e = h4; 89 | int f = 0; 90 | int k = 0; 91 | 92 | // main loop 93 | // 80份子明文分组进行4轮运算。 94 | for (int j = 0; j < 80; j++) { 95 | if (0 <= j && j <= 19) { 96 | f = (b & c) | ((~b) & d); 97 | k = 0x5A827999; 98 | } 99 | else if(20 <= j && j <= 39) { 100 | f = b ^ c ^ d; 101 | k = 0x6ED9EBA1; 102 | } 103 | else if(40 <= j && j <= 59) { 104 | f = (b & c) | (b & d) | (c & d); 105 | k = 0x8F1BBCDC; 106 | } 107 | else if(60 <= j && j <= 79) { 108 | f = b ^ c ^ d; 109 | k = 0xCA62C1D6; 110 | } 111 | 112 | int temp = left_rotate(a, 5) + f + e + k + w[j]; 113 | e = d; 114 | d = c; 115 | c = left_rotate(b, 30); 116 | b = a; 117 | a = temp; 118 | } 119 | 120 | // add chunk's hash to result 121 | // 链接变量与初始链接变量进行求和运算。 122 | // 链接变量作为下一个明文分组的输入重复进行以上操作。 123 | h0 = h0 + a; 124 | h1 = h1 + b; 125 | h2 = h2 + c; 126 | h3 = h3 + d; 127 | h4 = h4 + e; 128 | } 129 | 130 | // 最后,5个链接变量里面的数据就是SHA1摘要。 131 | byte[] hash = new byte[20]; 132 | 133 | for (int j = 0; j < 4; j++) { 134 | hash[j] = (byte) ((h0 >>> 24 - j * 8) & 0xFF); 135 | } 136 | 137 | for (int j = 0; j < 4; j++) { 138 | hash[j+4] = (byte) ((h1 >>> 24 - j * 8) & 0xFF); 139 | } 140 | 141 | for (int j = 0; j < 4; j++) { 142 | hash[j+8] = (byte) ((h2 >>> 24 - j * 8) & 0xFF); 143 | } 144 | 145 | for (int j = 0; j < 4; j++) { 146 | hash[j+12] = (byte) ((h3 >>> 24 - j * 8) & 0xFF); 147 | } 148 | 149 | for (int j = 0; j < 4; j++) { 150 | hash[j+16] = (byte) ((h4 >>> 24 - j * 8) & 0xFF); 151 | } 152 | 153 | return hash; 154 | } 155 | 156 | private static int left_rotate(int n, int d) { 157 | return (n << d) | (n >>> (32 - d)); 158 | } 159 | 160 | private int[] h = { 161 | 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 162 | }; 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/core/hash/SM3.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.hash; public class SM3 { } -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/util/ArrayUtil.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.util; 2 | 3 | import java.io.*; 4 | import java.math.BigInteger; 5 | 6 | public class ArrayUtil { 7 | 8 | /** 9 | * 将字符串转为一维short数组 10 | * transfer a string to short array 11 | * @param string target string to be process 12 | * @return a short array 13 | */ 14 | public static short[] transferToShorts(String string) { 15 | byte[] bytes = string.getBytes(); 16 | int length = bytes.length; 17 | short[] shorts = new short[length]; 18 | for (int i = 0; i < length; i++) { 19 | shorts[i] = bytes[i]; 20 | } 21 | return shorts; 22 | } 23 | 24 | /** 25 | * print information for tracing the whole process 26 | * 27 | * @param key info type 28 | * @param value info 29 | * @param nextRow flag deciding whether going to next row 30 | */ 31 | public static String printInfo(String key, String value, boolean nextRow) { 32 | String message = String.format("%-30s%-70s", key, value); 33 | if (nextRow) { 34 | message += "\n"; 35 | } 36 | System.out.println(message); 37 | return message; 38 | } 39 | 40 | /** 41 | * concatenate two byte arrays 42 | * @param before the first array in concat 43 | * @param after the second array in concat 44 | * @return concat 45 | */ 46 | public static byte[] concat(byte[] before, byte[] after) { 47 | byte[] result = new byte[before.length + after.length]; 48 | System.arraycopy(before, 0, result, 0, before.length); 49 | System.arraycopy(after, 0, result, before.length, after.length); 50 | return result; 51 | } 52 | 53 | /** 54 | * transfer int value into byte array 55 | * @param intValue int value 56 | * @return byte array 57 | */ 58 | public static byte[] int2Bytes(int intValue) { 59 | byte[] byteArray = null; 60 | try { 61 | ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); 62 | DataOutputStream dataOut = new DataOutputStream(byteOut); 63 | dataOut.writeByte(intValue); 64 | byteArray = byteOut.toByteArray(); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | return byteArray; 69 | } 70 | 71 | /** 72 | * segment one-dimension array into an 8x8 array 73 | * transfer every byte unit into int 74 | * transfer int into ascii type and print it 75 | * @param chars char array to be processed 76 | */ 77 | public static String segmentAndPrintChars(char[] chars) { 78 | char[][] chars1 = ArrayUtil.segmentDimension(chars, chars.length / 8 ,8); 79 | StringBuilder builder = new StringBuilder(); 80 | for (char[] aChars1 : chars1) { 81 | builder.append((char) Integer.parseInt(String.valueOf(aChars1), 2)); 82 | } 83 | return builder.toString(); 84 | } 85 | 86 | /** 87 | * transfer byte array into char array 88 | * @param bytes byte array to be transferred 89 | * @return bits in chars format 90 | */ 91 | public static char[] bytesToChars(byte[] bytes) { 92 | StringBuilder builder = new StringBuilder(); 93 | for (byte aByte : bytes) { 94 | String aByteStr = Integer.toBinaryString( 95 | (aByte & 0xff) + 0x0100).substring(1); 96 | builder.append(aByteStr); 97 | } 98 | return builder.toString().toCharArray(); 99 | } 100 | 101 | public static short[] byteToShorts(byte[] bytes) { 102 | short[] result = new short[bytes.length]; 103 | for (int i = 0; i < bytes.length; i++) { 104 | result[i] = (short) (bytes[i] & 0xff); 105 | } 106 | return result; 107 | } 108 | 109 | /** 110 | * disrupt the order of an array by reindexing it 111 | * @param chars original array to be disrupted 112 | * @param newIndexes index array the disruption is according to 113 | * @return disrupted sub array of chars 114 | */ 115 | public static char[] disruptArray(char[] chars, short[] newIndexes) { 116 | char[] resultChars = new char[newIndexes.length]; 117 | for (int i = 0; i < newIndexes.length; i++) { 118 | resultChars[i] = chars[newIndexes[i] - 1]; 119 | } 120 | return resultChars; 121 | } 122 | 123 | /** 124 | * byte array printing 125 | * @param bytes byte array 126 | */ 127 | public static void printByteArray(byte[] bytes){ 128 | int length = bytes.length; 129 | StringBuilder builder = new StringBuilder(); 130 | for (int i = 1; i <= length; i++) { 131 | String symbol = (i % 8 == 0) ? " " : ""; 132 | builder.append((int) bytes[i - 1]).append(symbol); 133 | } 134 | System.out.println(builder.toString()); 135 | } 136 | 137 | /** 138 | * print bits in chars format and what it stands for 139 | * @param prefix info 140 | * @param chars bits in chars format to be printed 141 | */ 142 | public static String printBitChars(String prefix, char[] chars) { 143 | int length = chars.length; 144 | StringBuilder builder = new StringBuilder(); 145 | for (int i = 1; i <= length; i++) { 146 | String symbol = (i % 8 == 0 || i == length) 147 | ? " " : ""; 148 | builder.append(chars[i - 1]).append(symbol); 149 | } 150 | String message = String.format("%-30s%-30s", prefix, builder.toString()); 151 | System.out.println(message); 152 | return message; 153 | } 154 | 155 | /** 156 | * char array printing 157 | * @param chars char array to be printed 158 | */ 159 | public static void printArray(char[] chars) { 160 | int length = chars.length; 161 | for (int i = 1; i <= length; i++) { 162 | String symbol = (i % 8 == 0 || i == length) 163 | ? "\n" : " "; 164 | System.out.print(chars[i - 1] + symbol); 165 | } 166 | } 167 | 168 | /** 169 | * left shifting based on String operation 170 | * @param src bits to be shifted in chars format 171 | * @param length shifting length 172 | * @return shifted bit sequences in chars format 173 | */ 174 | public static char[] leftShift(char[] src, int length) { 175 | String byteString = String.valueOf(src); 176 | return (byteString.substring(length) + 177 | byteString.substring(0, length)).toCharArray(); 178 | } 179 | 180 | /** 181 | * xor operation 182 | * @param aChars operating bits in chars format 183 | * @param bChars operating bits in chars format 184 | * @return result of operation, formatting in 48 or 64 bits 185 | */ 186 | public static char[] xor(char[] aChars, char[] bChars, int bits) { 187 | BigInteger a = new BigInteger(String.valueOf(aChars), 2); 188 | BigInteger b = new BigInteger(String.valueOf(bChars), 2); 189 | 190 | BigInteger xorResult = a.xor(b); 191 | 192 | String xorStr = xorResult.toString(2); 193 | StringBuilder builder = new StringBuilder(); 194 | 195 | int sub = bits - xorStr.length(); 196 | if (sub > 0) { 197 | for (int i = 0; i < sub; i++) { 198 | builder.append("0"); 199 | } 200 | xorStr = builder.toString() + xorStr; 201 | } 202 | return xorStr.toCharArray(); 203 | } 204 | 205 | /** 206 | * segment one-dimension array into a two-dimension array 207 | * which holds data in rows x columns format 208 | * @param chars one-dimension array 209 | * @param rows rows of result 210 | * @param columns columns of result 211 | * @return a two-dimension array 212 | * which holds data in rows x columns format 213 | */ 214 | public static char[][] segmentDimension(char[] chars, int rows, int columns) { 215 | char[][] result = new char[rows][columns]; 216 | for (int i = 0; i < result.length; i++) { 217 | System.arraycopy(chars, i * columns, result[i], 0, result[i].length); 218 | } 219 | return result; 220 | } 221 | 222 | /** 223 | * concatenate two arrays after left shifting in loop 224 | * @param before the first array in concat 225 | * @param after the second array in concat 226 | * @return concat 227 | */ 228 | public static char[] concat(char[] before, char[] after) { 229 | return (String.valueOf(before) + String.valueOf(after)) 230 | .toCharArray(); 231 | } 232 | 233 | /** 234 | * 获取文件字节数组 235 | * @param file 文件 236 | * @return 字节数组 237 | */ 238 | public static byte[] getBytes(File file){ 239 | byte[] buffer = null; 240 | FileInputStream fis = null; 241 | ByteArrayOutputStream bos = null; 242 | try { 243 | fis = new FileInputStream(file); 244 | bos = new ByteArrayOutputStream(1000); 245 | byte[] b = new byte[1000]; 246 | int n; 247 | while ((n = fis.read(b)) != -1) { 248 | bos.write(b, 0, n); 249 | } 250 | buffer = bos.toByteArray(); 251 | } catch (IOException e) { 252 | e.printStackTrace(); 253 | }finally { 254 | try { 255 | if (fis != null) { 256 | fis.close(); 257 | } 258 | } catch (IOException e) { 259 | e.printStackTrace(); 260 | }finally { 261 | if (bos != null) { 262 | try { 263 | bos.close(); 264 | } catch (IOException e) { 265 | e.printStackTrace(); 266 | } 267 | } 268 | } 269 | } 270 | return buffer; 271 | } 272 | } -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/util/Base64Util.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.Base64; 5 | 6 | /** 7 | * 通过Base64编码规则将不可见字符转化为可见字符 8 | * make it easy to print non printable and invisible characters 9 | * @author Jordon 10 | */ 11 | public class Base64Util { 12 | 13 | /** 14 | * 对字节数组进行编码 (AES) 15 | * encode byte array 16 | * @param bytes byte array 17 | * @return encoded string 18 | */ 19 | public static String encode(byte[] bytes) { 20 | return Base64.getEncoder().encodeToString(bytes); 21 | } 22 | 23 | /** 24 | * 将已经经过Base64编码的字符串解码成short数组 (AES) 25 | * decode a encoded string to short array 26 | * @param encodedText encoded text 27 | * @return short array 28 | */ 29 | public static short[] decodeToShorts(String encodedText) { 30 | return ArrayUtil.byteToShorts(Base64.getDecoder().decode(encodedText)); 31 | } 32 | 33 | /** 34 | * encode encrypted text bits by Base64 for processing unprintable (DES) 35 | * and invisible character 36 | * @param chars encrypted text bits 37 | * @return encoded text 38 | */ 39 | public static String encode(char[] chars) { 40 | char[][] segmentedChars = ArrayUtil.segmentDimension(chars, chars.length / 8, 8); 41 | byte[] bytes = new byte[0]; 42 | for (char[] segmentedChar : segmentedChars) { 43 | bytes = ArrayUtil.concat(bytes, ArrayUtil.int2Bytes( 44 | Integer.parseInt(String.valueOf(segmentedChar), 2))); 45 | } 46 | return Base64.getEncoder().encodeToString(bytes); 47 | } 48 | 49 | /** 50 | * decode decoded encrypted text bits in chars format (DES) 51 | * @param encodedText encoded text 52 | * @return encrypted text bits in chars format 53 | */ 54 | public static char[] decodeToChars(String encodedText) { 55 | return ArrayUtil.bytesToChars(Base64.getDecoder().decode(encodedText)); 56 | } 57 | 58 | /** 59 | * 将未处理的字符串用Base64编码 (RC4) 60 | * @param rawString 未处理的字符串 61 | * @return 编码后的字符串 62 | */ 63 | public static String encode(String rawString) { 64 | char[] chars = rawString.toCharArray(); 65 | byte[] bytes = new byte[0]; 66 | for (char c : chars) { 67 | bytes = ArrayUtil.concat(bytes, ArrayUtil.int2Bytes(c)); 68 | } 69 | return Base64.getEncoder().encodeToString(bytes); 70 | } 71 | 72 | /** 73 | * 将已用Base64编码的字符串解码 (RC4) 74 | * @param encodedText 已用Base64编码的字符串 75 | * @return 解码结果 76 | */ 77 | public static String decode(String encodedText) { 78 | StringBuilder builder = new StringBuilder(); 79 | byte[] bytes = Base64.getDecoder().decode(encodedText); 80 | for (byte b : bytes) { 81 | builder.append((char) (b & 0xff)); 82 | } 83 | return builder.toString(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/util/MathUtil.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.util; 2 | 3 | import java.util.concurrent.ThreadLocalRandom; 4 | 5 | public class MathUtil { 6 | // 最大公约数 7 | public static long gcd(long m, long n) { 8 | while(true){ 9 | if ((m = m % n) == 0) 10 | return n; 11 | if ((n = n % m) == 0) 12 | return m; 13 | } 14 | } 15 | 16 | /** 17 | * 求解线性同余方程 ax ≡ b(mod m) 18 | * @param a a 19 | * @param b b 20 | * @param m m 21 | * @return x 22 | */ 23 | public static long linearCongruence(long a, long b, long m) { 24 | if(b % gcd(a, m) != 0) 25 | return - 1; 26 | /* 27 | 通过扩展欧几里得算法求得x的逆元x' 28 | x = kx', b = k(a, m) 29 | 所以要求地 x = (b / gcd(a, m)) * x' 30 | */ 31 | long result = (b / gcd(a, m)) * extendedEuclid(a, m); 32 | if(result < 0) 33 | result += m; 34 | return result; 35 | } 36 | 37 | /** 38 | * 扩展欧几里得非递归实现 39 | * @param a 操作数 40 | * @param b 操作数 41 | */ 42 | private static long extendedEuclid(long a, long b) { 43 | long x = 0, y = 1, lastX = 1, lastY = 0, temp; 44 | 45 | if (a < b) { 46 | temp = a; 47 | a = b; 48 | b = temp; 49 | } 50 | 51 | while (b != 0) { 52 | long q = a / b, r = a % b; 53 | 54 | a = b; 55 | b = r; 56 | 57 | temp = x; 58 | x = lastX - q * x; 59 | lastX = temp; 60 | 61 | temp = y; 62 | y = lastY - q * y; 63 | lastY = temp; 64 | } 65 | return lastY; 66 | } 67 | 68 | /** 69 | * 随机生成一个可能是素数的数 70 | * @param range 随机数产生范围 71 | * @return 一个可能是素数的数 72 | */ 73 | public static long probablePrime(int range, int rounds) { 74 | if (range > 0 && rounds > 0) { 75 | ThreadLocalRandom random = ThreadLocalRandom.current(); 76 | while (true) { 77 | int num = random.nextInt(range) + 2; 78 | // 进行rounds轮素性测试 79 | if (PrimalityTester.isProbablePrime(num, rounds)) 80 | return num; 81 | } 82 | } 83 | return -1; 84 | } 85 | 86 | /** 87 | * 模幂运算(modular exponentiation)递归实现 88 | * @param x 底数 89 | * @param b 指数 90 | * @param n 模 91 | * @return x^b mod n 92 | */ 93 | public static long modExp(long x, long b, long n) { 94 | if (b == 0) return 1; 95 | // use long for intermediate computations to eliminate overflow 96 | long t = modExp(x, b / 2, n); 97 | long c = (t * t) % n; 98 | if (b % 2 == 1) 99 | c = (c * x) % n; 100 | return c; 101 | } 102 | /** 103 | * 模幂运算(modular exponentiation)递归实现 104 | * @param x 底数 105 | * @param b 指数 106 | * @param n 模 107 | * @return x^b mod n 108 | */ 109 | public static int exp(int x, int b, int n) { 110 | if (b == 1) { 111 | return x % n; 112 | } 113 | if ((b & 1) == 1) { // b是奇数 114 | return ((x % n) * exp(x, b - 1, n) % n); 115 | } 116 | // b是偶数 117 | long ans = exp(x, b / 2, n); 118 | return (int) (ans * ans) % n; 119 | } 120 | 121 | /** Function to calculate (a ^ b) % c **/ 122 | public static long modExpNonRec(long a, long b, long c) { 123 | long res = 1; 124 | for (int i = 0; i < b; i++) { 125 | res *= a; 126 | res %= c; 127 | } 128 | return res % c; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/util/PrimalityTester.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.util; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.ThreadLocalRandom; 5 | 6 | /** 7 | * 素性测试工具 8 | */ 9 | public class PrimalityTester { 10 | /** 11 | * 判断一个数是否素数,使用米勒-拉宾素性测试 12 | * @param n 待测奇数,大于3 13 | * @param rounds 测试轮数 14 | * @return 判断结果 15 | */ 16 | public static boolean isProbablePrime(long n, int rounds) { 17 | // 2是素数 18 | if (n == 2) 19 | return true; 20 | 21 | // n为偶数 22 | if ((n & 1) == 0) 23 | return false; 24 | 25 | // 把n-1写成(2^s)*d的形式 26 | long s = 0, d = n - 1, quotient, remainder; 27 | for (;;) { 28 | quotient = d / 2; 29 | remainder = d % 2; 30 | if (remainder == 1) 31 | break; 32 | s++; 33 | d = quotient; 34 | } 35 | 36 | Random rnd = ThreadLocalRandom.current(); 37 | // 进行k次米勒-拉宾测试 38 | for (int i = 0; i < rounds; i++) { 39 | // n肯定是合数,结束,不然n可能是素数,继续测试 40 | long a = Math.abs(rnd.nextLong()) % (n - 1) + 1; 41 | long b = MathUtil.modExpNonRec(a, d , n); 42 | 43 | if (b == 1 || b == n - 1) { 44 | continue; 45 | } 46 | int j = 0; 47 | for (; j < s; j++) { 48 | b = MathUtil.modExpNonRec(b, 2, n); 49 | if (b == 1) { 50 | return false; 51 | } 52 | if (b == n - 1) 53 | break; 54 | } 55 | if (j == s) // None of the steps mad x equals n-1. 56 | return false; 57 | } 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/AESView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Fri Nov 16 22:27:55 CST 2018 3 | */ 4 | 5 | package org.jordon.security.view; 6 | 7 | import java.awt.*; 8 | import javax.swing.*; 9 | import javax.swing.GroupLayout; 10 | import javax.swing.LayoutStyle; 11 | 12 | /** 13 | * @author Jasion 14 | */ 15 | public class AESView extends JFrame { 16 | 17 | 18 | public AESView() { 19 | initComponents(); 20 | } 21 | 22 | private void initComponents() { 23 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 24 | // Generated using JFormDesigner Evaluation license - Jasion 25 | textArea1 = new JTextArea(); 26 | scrollPane1 = new JScrollPane(); 27 | ptArea = new JTextArea(); 28 | label1 = new JLabel(); 29 | label2 = new JLabel(); 30 | keyField = new JTextField(); 31 | label3 = new JLabel(); 32 | scrollPane2 = new JScrollPane(); 33 | cipherArea = new JTextArea(); 34 | processPanel = new JScrollPane(); 35 | processArea = new JTextArea(); 36 | label4 = new JLabel(); 37 | 38 | //======== this ======== 39 | Container contentPane = getContentPane(); 40 | 41 | //======== scrollPane1 ======== 42 | { 43 | scrollPane1.setViewportView(ptArea); 44 | } 45 | 46 | //---- label1 ---- 47 | label1.setText("\u660e\u6587"); 48 | 49 | //---- label2 ---- 50 | label2.setText("\u5bc6\u94a5"); 51 | 52 | //---- label3 ---- 53 | label3.setText("\u5bc6\u6587"); 54 | 55 | //======== scrollPane2 ======== 56 | { 57 | scrollPane2.setViewportView(cipherArea); 58 | } 59 | 60 | //======== processPanel ======== 61 | { 62 | processPanel.setViewportView(processArea); 63 | } 64 | 65 | //---- label4 ---- 66 | label4.setText("\u8be6\u7ec6\u8fc7\u7a0b"); 67 | 68 | GroupLayout contentPaneLayout = new GroupLayout(contentPane); 69 | contentPane.setLayout(contentPaneLayout); 70 | contentPaneLayout.setHorizontalGroup( 71 | contentPaneLayout.createParallelGroup() 72 | .addGroup(contentPaneLayout.createSequentialGroup() 73 | .addGap(21, 21, 21) 74 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) 75 | .addComponent(label1) 76 | .addComponent(textArea1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 77 | .addComponent(label2) 78 | .addComponent(label3)) 79 | .addGap(18, 18, 18) 80 | .addGroup(contentPaneLayout.createParallelGroup() 81 | .addComponent(keyField, GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE) 82 | .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE) 83 | .addComponent(scrollPane2, GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE)) 84 | .addGap(35, 35, 35)) 85 | .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup() 86 | .addContainerGap(24, Short.MAX_VALUE) 87 | .addComponent(label4, GroupLayout.PREFERRED_SIZE, 57, GroupLayout.PREFERRED_SIZE) 88 | .addGap(602, 602, 602)) 89 | .addGroup(contentPaneLayout.createSequentialGroup() 90 | .addGap(19, 19, 19) 91 | .addComponent(processPanel, GroupLayout.PREFERRED_SIZE, 644, GroupLayout.PREFERRED_SIZE) 92 | .addContainerGap(20, Short.MAX_VALUE)) 93 | ); 94 | contentPaneLayout.setVerticalGroup( 95 | contentPaneLayout.createParallelGroup() 96 | .addGroup(contentPaneLayout.createSequentialGroup() 97 | .addGroup(contentPaneLayout.createParallelGroup() 98 | .addGroup(contentPaneLayout.createSequentialGroup() 99 | .addGap(41, 41, 41) 100 | .addComponent(label1)) 101 | .addGroup(contentPaneLayout.createSequentialGroup() 102 | .addGap(20, 20, 20) 103 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE))) 104 | .addGap(25, 25, 25) 105 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 106 | .addComponent(label2) 107 | .addComponent(keyField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) 108 | .addGroup(contentPaneLayout.createParallelGroup() 109 | .addGroup(contentPaneLayout.createSequentialGroup() 110 | .addGap(52, 52, 52) 111 | .addComponent(label3)) 112 | .addGroup(contentPaneLayout.createSequentialGroup() 113 | .addGap(25, 25, 25) 114 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE))) 115 | .addGap(8, 8, 8) 116 | .addComponent(label4) 117 | .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) 118 | .addComponent(processPanel, GroupLayout.PREFERRED_SIZE, 306, GroupLayout.PREFERRED_SIZE) 119 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 120 | .addComponent(textArea1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 121 | .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 122 | ); 123 | pack(); 124 | setLocationRelativeTo(getOwner()); 125 | // JFormDesigner - End of component initialization //GEN-END:initComponents 126 | } 127 | 128 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 129 | // Generated using JFormDesigner Evaluation license - Jasion 130 | private JTextArea textArea1; 131 | private JScrollPane scrollPane1; 132 | private JTextArea ptArea; 133 | private JLabel label1; 134 | private JLabel label2; 135 | private JTextField keyField; 136 | private JLabel label3; 137 | private JScrollPane scrollPane2; 138 | private JTextArea cipherArea; 139 | private JScrollPane processPanel; 140 | private JTextArea processArea; 141 | private JLabel label4; 142 | // JFormDesigner - End of variables declaration //GEN-END:variables 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/AESView.jfd: -------------------------------------------------------------------------------- 1 | JFDML JFormDesigner: "6.0.4.1.172" Java: "1.8.0_152-release" encoding: "UTF-8" 2 | 3 | new FormModel { 4 | contentType: "form/swing" 5 | root: new FormRoot { 6 | add( new FormWindow( "javax.swing.JFrame", new FormLayoutManager( class org.jdesktop.layout.GroupLayout ) { 7 | "$horizontalGroup": "par l {seq l {space :p:21:p, par t {comp label1:::p::p, comp textArea1:::p::p, comp label2::t:p::p, comp label3:::p::p}, space s:::p, par l {comp keyField::::585:x, comp scrollPane1::::585:x, comp scrollPane2::l::585:x}, space :p:35:p}, seq t {space ::24:x, comp label4:::p:57:p, space :p:602:p}, seq l {space :p:19:p, comp processPanel:::p:644:p, space ::20:x}}" 8 | "$verticalGroup": "par l {seq l {par l {seq {space :p:41:p, comp label1:::p::p}, seq {space :p:20:p, comp scrollPane1:::p:60:p}}, space :p:25:p, par b {comp label2::b:p::p, comp keyField::b:p::p}, par l {seq {space :p:52:p, comp label3:::p::p}, seq l {space :p:25:p, comp scrollPane2:::p:60:p}}, space :p:8:p, comp label4:::p::p, space u:::p, comp processPanel:::p:306:p, space :::p, comp textArea1:::p::p, space :::x}}" 9 | } ) { 10 | name: "this" 11 | add( new FormComponent( "javax.swing.JTextArea" ) { 12 | name: "textArea1" 13 | } ) 14 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 15 | name: "scrollPane1" 16 | add( new FormComponent( "javax.swing.JTextArea" ) { 17 | name: "ptArea" 18 | } ) 19 | } ) 20 | add( new FormComponent( "javax.swing.JLabel" ) { 21 | name: "label1" 22 | "text": "明文" 23 | } ) 24 | add( new FormComponent( "javax.swing.JLabel" ) { 25 | name: "label2" 26 | "text": "密钥" 27 | } ) 28 | add( new FormComponent( "javax.swing.JTextField" ) { 29 | name: "keyField" 30 | } ) 31 | add( new FormComponent( "javax.swing.JLabel" ) { 32 | name: "label3" 33 | "text": "密文" 34 | } ) 35 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 36 | name: "scrollPane2" 37 | add( new FormComponent( "javax.swing.JTextArea" ) { 38 | name: "cipherArea" 39 | } ) 40 | } ) 41 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 42 | name: "processPanel" 43 | add( new FormComponent( "javax.swing.JTextArea" ) { 44 | name: "processArea" 45 | } ) 46 | } ) 47 | add( new FormComponent( "javax.swing.JLabel" ) { 48 | name: "label4" 49 | "text": "详细过程" 50 | } ) 51 | }, new FormLayoutConstraints( null ) { 52 | "location": new java.awt.Point( 15, 0 ) 53 | "size": new java.awt.Dimension( 685, 605 ) 54 | } ) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/DESView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Fri Nov 16 22:25:20 CST 2018 3 | */ 4 | 5 | package org.jordon.security.view; 6 | 7 | import org.jordon.security.core.crypto.symmetry.DESCipherService; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | import java.awt.event.ActionEvent; 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.io.UnsupportedEncodingException; 15 | import java.util.List; 16 | 17 | /** 18 | * @author Jordon 19 | */ 20 | public class DESView extends JFrame { 21 | 22 | private DESCipherService desCipherService; 23 | 24 | public static void main(String[] args) { 25 | new DESView(); 26 | } 27 | 28 | public DESView() { 29 | initComponents(); 30 | desCipherService = new DESCipherService(true); 31 | } 32 | 33 | // 加密按钮事件处理 34 | private void encButtonActionPerformed(ActionEvent e) { 35 | desCipherService.setWorkingMode((String) workComboBox.getSelectedItem()); 36 | String plaintext = ptArea.getText(); 37 | String key = keyField.getText(); 38 | String cipher = ""; 39 | try { 40 | cipher = desCipherService.encrypt(plaintext, key); 41 | } catch (UnsupportedEncodingException e1) { 42 | e1.printStackTrace(); 43 | } 44 | cipherArea.setText(cipher); 45 | 46 | printDetails(); 47 | } 48 | 49 | private void printDetails() { 50 | processArea.setText(""); 51 | List messages = desCipherService.getMessages(); 52 | for (String msg : messages) { 53 | processArea.append(msg + "\n"); 54 | // 激活自动换行功能 55 | processArea.setLineWrap(true); 56 | processArea.setCaretPosition(processArea.getDocument().getLength()); 57 | processArea.paintImmediately(processArea.getBounds()); 58 | processArea.setWrapStyleWord(true); 59 | // enable the style of String.formatting result 60 | processArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); 61 | } 62 | desCipherService.clearMessages(); 63 | } 64 | 65 | // 解密按钮事件处理 66 | private void decButtonActionPerformed(ActionEvent e) { 67 | String cipher = cipherArea.getText(); 68 | String key = keyField.getText(); 69 | String plaintext = ""; 70 | try { 71 | plaintext = desCipherService.decrypt(cipher, key); 72 | } catch (UnsupportedEncodingException e1) { 73 | e1.printStackTrace(); 74 | } 75 | ptArea.setText(plaintext); 76 | 77 | printDetails(); 78 | } 79 | 80 | private void chooserButtonActionPerformed(ActionEvent e) { 81 | // 创建文件选择器 82 | JFileChooser fileChooser = new JFileChooser("."); 83 | fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 84 | fileChooser.setMultiSelectionEnabled(false); 85 | fileChooser.showOpenDialog(this); 86 | // 返回选中的文件集 87 | File selectedFile = fileChooser.getSelectedFile(); 88 | 89 | String cipher; 90 | try { 91 | ptArea.setText("encryptinng " + selectedFile.getName()); 92 | desCipherService.setWorkingMode((String) workComboBox.getSelectedItem()); 93 | cipher = desCipherService.encryptFile(selectedFile, keyField.getText()); 94 | cipherArea.setText(cipher); 95 | } catch (UnsupportedEncodingException | FileNotFoundException e1) { 96 | e1.printStackTrace(); 97 | } 98 | } 99 | 100 | 101 | private void initComponents() { 102 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 103 | // Generated using JFormDesigner Evaluation license - Jasion 104 | textArea1 = new JTextArea(); 105 | scrollPane1 = new JScrollPane(); 106 | ptArea = new JTextArea(); 107 | label1 = new JLabel(); 108 | label2 = new JLabel(); 109 | keyField = new JTextField(); 110 | label3 = new JLabel(); 111 | scrollPane2 = new JScrollPane(); 112 | cipherArea = new JTextArea(); 113 | processPanel = new JScrollPane(); 114 | processArea = new JTextArea(); 115 | processLabel = new JLabel(); 116 | decButton = new JButton(); 117 | encButton = new JButton(); 118 | padComboBox = new JComboBox(); 119 | workComboBox = new JComboBox(); 120 | label5 = new JLabel(); 121 | label6 = new JLabel(); 122 | chooserButton = new JButton(); 123 | 124 | //======== this ======== 125 | setTitle("DES-Jordon Yang"); 126 | Container contentPane = getContentPane(); 127 | 128 | //======== scrollPane1 ======== 129 | { 130 | scrollPane1.setViewportView(ptArea); 131 | } 132 | ptArea.setLineWrap(true); // 激活自动换行功能 133 | ptArea.setWrapStyleWord(true); // 激活断行不断字功能 134 | //---- label1 ---- 135 | label1.setText("\u660e\u6587"); 136 | 137 | //---- label2 ---- 138 | label2.setText("\u5bc6\u94a5"); 139 | 140 | //---- label3 ---- 141 | label3.setText("\u5bc6\u6587"); 142 | 143 | //======== scrollPane2 ======== 144 | { 145 | scrollPane2.setViewportView(cipherArea); 146 | } 147 | cipherArea.setLineWrap(true); // 激活自动换行功能 148 | cipherArea.setWrapStyleWord(true); // 激活断行不断字功能 149 | //======== processPanel ======== 150 | { 151 | processPanel.setViewportView(processArea); 152 | } 153 | 154 | //---- processLabel ---- 155 | processLabel.setText("\u8be6\u7ec6\u8fc7\u7a0b"); 156 | 157 | //---- decButton ---- 158 | decButton.setText("\u89e3\u5bc6"); 159 | decButton.addActionListener(e -> decButtonActionPerformed(e)); 160 | 161 | //---- encButton ---- 162 | encButton.setText("\u52a0\u5bc6"); 163 | encButton.addActionListener(e -> encButtonActionPerformed(e)); 164 | 165 | //---- label5 ---- 166 | label5.setText("\u586b\u5145\u65b9\u5f0f"); 167 | 168 | //---- label6 ---- 169 | label6.setText("\u5de5\u4f5c\u6a21\u5f0f"); 170 | 171 | //---- chooserButton ---- 172 | chooserButton.setText("\u9009\u62e9\u6587\u4ef6"); 173 | chooserButton.addActionListener(e -> { 174 | encButtonActionPerformed(e); 175 | chooserButtonActionPerformed(e); 176 | }); 177 | 178 | GroupLayout contentPaneLayout = new GroupLayout(contentPane); 179 | contentPane.setLayout(contentPaneLayout); 180 | contentPaneLayout.setHorizontalGroup( 181 | contentPaneLayout.createParallelGroup() 182 | .addGroup(contentPaneLayout.createSequentialGroup() 183 | .addContainerGap(20, Short.MAX_VALUE) 184 | .addGroup(contentPaneLayout.createParallelGroup() 185 | .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup() 186 | .addGap(58, 58, 58) 187 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING, false) 188 | .addGroup(contentPaneLayout.createSequentialGroup() 189 | .addComponent(label5) 190 | .addGap(46, 46, 46) 191 | .addComponent(padComboBox, GroupLayout.PREFERRED_SIZE, 136, GroupLayout.PREFERRED_SIZE) 192 | .addGap(80, 80, 80) 193 | .addComponent(label6, GroupLayout.PREFERRED_SIZE, 62, GroupLayout.PREFERRED_SIZE) 194 | .addGap(58, 58, 58)) 195 | .addGroup(contentPaneLayout.createSequentialGroup() 196 | .addGap(83, 83, 83) 197 | .addComponent(chooserButton, GroupLayout.PREFERRED_SIZE, 128, GroupLayout.PREFERRED_SIZE) 198 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 199 | .addComponent(encButton, GroupLayout.PREFERRED_SIZE, 68, GroupLayout.PREFERRED_SIZE) 200 | .addGap(87, 87, 87))) 201 | .addGroup(contentPaneLayout.createParallelGroup() 202 | .addComponent(workComboBox, GroupLayout.PREFERRED_SIZE, 140, GroupLayout.PREFERRED_SIZE) 203 | .addComponent(decButton, GroupLayout.PREFERRED_SIZE, 68, GroupLayout.PREFERRED_SIZE)) 204 | .addGap(190, 190, 190)) 205 | .addGroup(contentPaneLayout.createSequentialGroup() 206 | .addGroup(contentPaneLayout.createParallelGroup() 207 | .addComponent(processPanel, GroupLayout.PREFERRED_SIZE, 790, GroupLayout.PREFERRED_SIZE) 208 | .addComponent(processLabel, GroupLayout.PREFERRED_SIZE, 57, GroupLayout.PREFERRED_SIZE)) 209 | .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) 210 | .addGroup(contentPaneLayout.createSequentialGroup() 211 | .addGap(21, 21, 21) 212 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) 213 | .addComponent(label1) 214 | .addComponent(textArea1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 215 | .addComponent(label2) 216 | .addComponent(label3)) 217 | .addGap(18, 18, 18) 218 | .addGroup(contentPaneLayout.createParallelGroup() 219 | .addComponent(keyField, GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE) 220 | .addComponent(scrollPane1, GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE) 221 | .addComponent(scrollPane2, GroupLayout.DEFAULT_SIZE, 740, Short.MAX_VALUE)) 222 | .addGap(35, 35, 35)) 223 | ); 224 | contentPaneLayout.setVerticalGroup( 225 | contentPaneLayout.createParallelGroup() 226 | .addGroup(contentPaneLayout.createSequentialGroup() 227 | .addGroup(contentPaneLayout.createParallelGroup() 228 | .addGroup(contentPaneLayout.createSequentialGroup() 229 | .addGap(41, 41, 41) 230 | .addComponent(label1)) 231 | .addGroup(contentPaneLayout.createSequentialGroup() 232 | .addGap(20, 20, 20) 233 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE))) 234 | .addGap(25, 25, 25) 235 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 236 | .addComponent(label2) 237 | .addComponent(keyField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) 238 | .addGroup(contentPaneLayout.createParallelGroup() 239 | .addGroup(contentPaneLayout.createSequentialGroup() 240 | .addGap(52, 52, 52) 241 | .addComponent(label3) 242 | .addGap(40, 40, 40)) 243 | .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup() 244 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 245 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 76, GroupLayout.PREFERRED_SIZE) 246 | .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED))) 247 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 248 | .addComponent(label5) 249 | .addComponent(label6) 250 | .addComponent(workComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 251 | .addComponent(padComboBox, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) 252 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE) 253 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 254 | .addComponent(decButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) 255 | .addComponent(encButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE) 256 | .addComponent(chooserButton, GroupLayout.PREFERRED_SIZE, 33, GroupLayout.PREFERRED_SIZE)) 257 | .addGap(39, 39, 39) 258 | .addComponent(processLabel) 259 | .addGap(26, 26, 26) 260 | .addGroup(contentPaneLayout.createParallelGroup() 261 | .addGroup(contentPaneLayout.createSequentialGroup() 262 | .addGap(0, 0, Short.MAX_VALUE) 263 | .addComponent(textArea1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 264 | .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) 265 | .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup() 266 | .addComponent(processPanel, GroupLayout.PREFERRED_SIZE, 306, GroupLayout.PREFERRED_SIZE) 267 | .addContainerGap()))) 268 | ); 269 | pack(); 270 | setLocationRelativeTo(getOwner()); 271 | // JFormDesigner - End of component initialization //GEN-END:initComponents 272 | setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 273 | setLocationRelativeTo(null); 274 | setVisible(true); 275 | padComboBox.addItem("标记位数填充"); 276 | 277 | workComboBox.addItem("ECB"); 278 | workComboBox.addItem("CBC"); 279 | workComboBox.addItem("CTR"); 280 | } 281 | 282 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 283 | // Generated using JFormDesigner Evaluation license - Jasion 284 | private JTextArea textArea1; 285 | private JScrollPane scrollPane1; 286 | private JTextArea ptArea; 287 | private JLabel label1; 288 | private JLabel label2; 289 | private JTextField keyField; 290 | private JLabel label3; 291 | private JScrollPane scrollPane2; 292 | private JTextArea cipherArea; 293 | private JScrollPane processPanel; 294 | private JTextArea processArea; 295 | private JLabel processLabel; 296 | private JButton decButton; 297 | private JButton encButton; 298 | private JComboBox padComboBox; 299 | private JComboBox workComboBox; 300 | private JLabel label5; 301 | private JLabel label6; 302 | private JButton chooserButton; 303 | // JFormDesigner - End of variables declaration //GEN-END:variables 304 | } 305 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/DESView.jfd: -------------------------------------------------------------------------------- 1 | JFDML JFormDesigner: "6.0.4.1.172" Java: "1.8.0_152-release" encoding: "UTF-8" 2 | 3 | new FormModel { 4 | contentType: "form/swing" 5 | root: new FormRoot { 6 | add( new FormWindow( "javax.swing.JFrame", new FormLayoutManager( class org.jdesktop.layout.GroupLayout ) { 7 | "$horizontalGroup": "par l {seq {space ::20:x, par l {seq t {space :p:58:p, par t:::p {seq {comp label5:::p::p, space :p:46:p, comp padComboBox:::p:136:p, space :p:80:p, comp label6:::p:62:p, space :p:58:p}, seq t {space :p:83:p, comp chooserButton:::p:128:p, space :::x, comp encButton:::p:68:p, space :p:87:p}}, par l {comp workComboBox:::p:140:p, comp decButton:::p:68:p}, space :p:190:p}, seq {par l {comp processPanel:::p:790:p, comp processLabel:::p:57:p}, space :::x}}}, seq l {space :p:21:p, par t {comp label1:::p::p, comp textArea1:::p::p, comp label2::t:p::p, comp label3:::p::p}, space s:::p, par l {comp keyField::::740:x, comp scrollPane1::::740:x, comp scrollPane2::l::740:x}, space :p:35:p}}" 8 | "$verticalGroup": "par l {seq l {par l {seq {space :p:41:p, comp label1:::p::p}, seq {space :p:20:p, comp scrollPane1:::p:60:p}}, space :p:25:p, par b {comp label2::b:p::p, comp keyField::b:p::p}, par l {seq {space :p:52:p, comp label3:::p::p, space :p:40:p}, seq t {space :::p, comp scrollPane2:::p:76:p, space u:::p}}, par b {comp label5::b:p::p, comp label6::b:p::p, comp workComboBox::b:p::p, comp padComboBox::b:p::p}, space ::33:x, par b {comp decButton::b:p:33:p, comp encButton::b:p:33:p, comp chooserButton::b:p:33:p}, space :p:39:p, comp processLabel:::p::p, space :p:26:p, par l {seq {space :0:0:x, comp textArea1:::p::p, space :::x}, seq t {comp processPanel:::p:306:p, space :::p}}}}" 9 | } ) { 10 | name: "this" 11 | "title": "DES-Jordon Yang" 12 | add( new FormComponent( "javax.swing.JTextArea" ) { 13 | name: "textArea1" 14 | } ) 15 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 16 | name: "scrollPane1" 17 | add( new FormComponent( "javax.swing.JTextArea" ) { 18 | name: "ptArea" 19 | } ) 20 | } ) 21 | add( new FormComponent( "javax.swing.JLabel" ) { 22 | name: "label1" 23 | "text": "明文" 24 | } ) 25 | add( new FormComponent( "javax.swing.JLabel" ) { 26 | name: "label2" 27 | "text": "密钥" 28 | } ) 29 | add( new FormComponent( "javax.swing.JTextField" ) { 30 | name: "keyField" 31 | } ) 32 | add( new FormComponent( "javax.swing.JLabel" ) { 33 | name: "label3" 34 | "text": "密文" 35 | } ) 36 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 37 | name: "scrollPane2" 38 | add( new FormComponent( "javax.swing.JTextArea" ) { 39 | name: "cipherArea" 40 | } ) 41 | } ) 42 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 43 | name: "processPanel" 44 | add( new FormComponent( "javax.swing.JTextArea" ) { 45 | name: "processArea" 46 | } ) 47 | } ) 48 | add( new FormComponent( "javax.swing.JLabel" ) { 49 | name: "processLabel" 50 | "text": "详细过程" 51 | } ) 52 | add( new FormComponent( "javax.swing.JButton" ) { 53 | name: "decButton" 54 | "text": "解密" 55 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decButtonActionPerformed", true ) ) 56 | } ) 57 | add( new FormComponent( "javax.swing.JButton" ) { 58 | name: "encButton" 59 | "text": "加密" 60 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "encButtonActionPerformed", true ) ) 61 | } ) 62 | add( new FormComponent( "javax.swing.JComboBox" ) { 63 | name: "padComboBox" 64 | } ) 65 | add( new FormComponent( "javax.swing.JComboBox" ) { 66 | name: "workComboBox" 67 | } ) 68 | add( new FormComponent( "javax.swing.JLabel" ) { 69 | name: "label5" 70 | "text": "填充方式" 71 | } ) 72 | add( new FormComponent( "javax.swing.JLabel" ) { 73 | name: "label6" 74 | "text": "工作模式" 75 | } ) 76 | add( new FormComponent( "javax.swing.JButton" ) { 77 | name: "chooserButton" 78 | "text": "选择文件" 79 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "encButtonActionPerformed", true ) ) 80 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "chooserButtonActionPerformed", true ) ) 81 | } ) 82 | }, new FormLayoutConstraints( null ) { 83 | "location": new java.awt.Point( 15, 0 ) 84 | "size": new java.awt.Dimension( 840, 755 ) 85 | } ) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/RSABigIntegerView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Fri Nov 30 12:46:09 CST 2018 3 | */ 4 | 5 | package org.jordon.security.view; 6 | 7 | import org.jordon.security.core.crypto.assymmetry.RSACipherService; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | import java.awt.event.ActionEvent; 12 | import java.math.BigInteger; 13 | import java.security.SecureRandom; 14 | 15 | /** 16 | * @author Jasion 17 | */ 18 | public class RSABigIntegerView extends JFrame { 19 | private RSACipherService service = new RSACipherService(2 << 10); 20 | private final static SecureRandom random = new SecureRandom(); 21 | private static final int N = 1024; 22 | RSACipherService key = new RSACipherService(N); 23 | 24 | public static void main(String[] args) { 25 | RSABigIntegerView view = new RSABigIntegerView(); 26 | view.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 27 | view.setLocationRelativeTo(null); 28 | view.setVisible(true); 29 | } 30 | 31 | public RSABigIntegerView() { 32 | initComponents(); 33 | eField.setText(key.getPublicKey().toString(10)); 34 | dArea.setText(key.getPrivateKey().toString(10)); 35 | nArea.setText(key.getModulus().toString(10)); 36 | } 37 | 38 | private void encButtonActionPerformed(ActionEvent e) { 39 | BigInteger message = new BigInteger(ptArea.getText(), 10); 40 | BigInteger encrypt = key.encrypt(message); 41 | cArea.setText(encrypt.toString(10)); 42 | } 43 | 44 | private void decButtonActionPerformed(ActionEvent e) { 45 | BigInteger decrypt = key.decrypt(new BigInteger(cArea.getText(), 10)); 46 | ptArea.setText(decrypt.toString(10)); 47 | } 48 | 49 | private void initComponents() { 50 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 51 | // Generated using JFormDesigner Evaluation license - Jasion 52 | label1 = new JLabel(); 53 | eField = new JTextField(); 54 | label2 = new JLabel(); 55 | scrollPane1 = new JScrollPane(); 56 | dArea = new JTextArea(); 57 | label3 = new JLabel(); 58 | scrollPane2 = new JScrollPane(); 59 | nArea = new JTextArea(); 60 | label4 = new JLabel(); 61 | scrollPane = new JScrollPane(); 62 | ptArea = new JTextArea(); 63 | label5 = new JLabel(); 64 | scrollPane4 = new JScrollPane(); 65 | cArea = new JTextArea(); 66 | encButton = new JButton(); 67 | decButton = new JButton(); 68 | 69 | //======== this ======== 70 | Container contentPane = getContentPane(); 71 | setTitle("RSA - jordonyang"); 72 | //---- label1 ---- 73 | label1.setText("\u516c\u94a5e"); 74 | label1.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 75 | 76 | //---- eField ---- 77 | eField.setEditable(false); 78 | 79 | //---- label2 ---- 80 | label2.setText("\u79c1\u94a5d"); 81 | label2.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 82 | 83 | //======== scrollPane1 ======== 84 | { 85 | 86 | //---- dArea ---- 87 | dArea.setEditable(false); 88 | scrollPane1.setViewportView(dArea); 89 | } 90 | dArea.setLineWrap(true); // 激活自动换行功能 91 | dArea.setWrapStyleWord(true); // 激活断行不断字功能 92 | 93 | //---- label3 ---- 94 | label3.setText("\u6a21n"); 95 | label3.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 96 | 97 | //======== scrollPane2 ======== 98 | { 99 | 100 | //---- nArea ---- 101 | nArea.setEditable(false); 102 | scrollPane2.setViewportView(nArea); 103 | } 104 | nArea.setLineWrap(true); // 激活自动换行功能 105 | nArea.setWrapStyleWord(true); // 激活断行不断字功能 106 | 107 | //---- label4 ---- 108 | label4.setText("\u660e\u6587"); 109 | label4.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 110 | 111 | //======== scrollPane ======== 112 | { 113 | scrollPane.setViewportView(ptArea); 114 | } 115 | ptArea.setLineWrap(true); // 激活自动换行功能 116 | ptArea.setWrapStyleWord(true); // 激活断行不断字功能 117 | 118 | //---- label5 ---- 119 | label5.setText("\u5bc6\u6587"); 120 | label5.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 121 | 122 | //======== scrollPane4 ======== 123 | { 124 | scrollPane4.setViewportView(cArea); 125 | } 126 | cArea.setLineWrap(true); // 激活自动换行功能 127 | cArea.setWrapStyleWord(true); // 激活断行不断字功能 128 | 129 | //---- encButton ---- 130 | encButton.setText("\u52a0\u5bc6"); 131 | encButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 132 | encButton.addActionListener(e -> encButtonActionPerformed(e)); 133 | 134 | //---- decButton ---- 135 | decButton.setText("\u89e3\u5bc6"); 136 | decButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 137 | decButton.addActionListener(e -> decButtonActionPerformed(e)); 138 | 139 | GroupLayout contentPaneLayout = new GroupLayout(contentPane); 140 | contentPane.setLayout(contentPaneLayout); 141 | contentPaneLayout.setHorizontalGroup( 142 | contentPaneLayout.createParallelGroup() 143 | .addGroup(contentPaneLayout.createSequentialGroup() 144 | .addGroup(contentPaneLayout.createParallelGroup() 145 | .addGroup(contentPaneLayout.createSequentialGroup() 146 | .addGap(24, 24, 24) 147 | .addGroup(contentPaneLayout.createParallelGroup() 148 | .addGroup(contentPaneLayout.createSequentialGroup() 149 | .addComponent(label1) 150 | .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) 151 | .addComponent(eField, GroupLayout.PREFERRED_SIZE, 648, GroupLayout.PREFERRED_SIZE)) 152 | .addGroup(contentPaneLayout.createSequentialGroup() 153 | .addGroup(contentPaneLayout.createParallelGroup() 154 | .addComponent(label2) 155 | .addComponent(label3) 156 | .addComponent(label4) 157 | .addComponent(label5, GroupLayout.PREFERRED_SIZE, 42, GroupLayout.PREFERRED_SIZE)) 158 | .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) 159 | .addGroup(contentPaneLayout.createParallelGroup() 160 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 647, GroupLayout.PREFERRED_SIZE) 161 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 647, GroupLayout.PREFERRED_SIZE) 162 | .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 647, GroupLayout.PREFERRED_SIZE) 163 | .addComponent(scrollPane4, GroupLayout.PREFERRED_SIZE, 647, GroupLayout.PREFERRED_SIZE))))) 164 | .addGroup(contentPaneLayout.createSequentialGroup() 165 | .addGap(242, 242, 242) 166 | .addComponent(encButton) 167 | .addGap(119, 119, 119) 168 | .addComponent(decButton))) 169 | .addContainerGap(38, Short.MAX_VALUE)) 170 | ); 171 | contentPaneLayout.setVerticalGroup( 172 | contentPaneLayout.createParallelGroup() 173 | .addGroup(contentPaneLayout.createSequentialGroup() 174 | .addGap(18, 18, 18) 175 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 176 | .addComponent(label1) 177 | .addComponent(eField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) 178 | .addGap(30, 30, 30) 179 | .addGroup(contentPaneLayout.createParallelGroup() 180 | .addComponent(label2) 181 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 92, GroupLayout.PREFERRED_SIZE)) 182 | .addGap(34, 34, 34) 183 | .addGroup(contentPaneLayout.createParallelGroup() 184 | .addComponent(label3) 185 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)) 186 | .addGroup(contentPaneLayout.createParallelGroup() 187 | .addGroup(contentPaneLayout.createSequentialGroup() 188 | .addGap(38, 38, 38) 189 | .addComponent(label4)) 190 | .addGroup(contentPaneLayout.createSequentialGroup() 191 | .addGap(46, 46, 46) 192 | .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE))) 193 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE) 194 | .addGroup(contentPaneLayout.createParallelGroup() 195 | .addComponent(label5) 196 | .addComponent(scrollPane4, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)) 197 | .addGap(40, 40, 40) 198 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 199 | .addComponent(decButton) 200 | .addComponent(encButton)) 201 | .addGap(41, 41, 41)) 202 | ); 203 | pack(); 204 | setLocationRelativeTo(getOwner()); 205 | // JFormDesigner - End of component initialization //GEN-END:initComponents 206 | } 207 | 208 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 209 | // Generated using JFormDesigner Evaluation license - Jasion 210 | private JLabel label1; 211 | private JTextField eField; 212 | private JLabel label2; 213 | private JScrollPane scrollPane1; 214 | private JTextArea dArea; 215 | private JLabel label3; 216 | private JScrollPane scrollPane2; 217 | private JTextArea nArea; 218 | private JLabel label4; 219 | private JScrollPane scrollPane; 220 | private JTextArea ptArea; 221 | private JLabel label5; 222 | private JScrollPane scrollPane4; 223 | private JTextArea cArea; 224 | private JButton encButton; 225 | private JButton decButton; 226 | // JFormDesigner - End of variables declaration //GEN-END:variables 227 | } 228 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/RSABigIntegerView.jfd: -------------------------------------------------------------------------------- 1 | JFDML JFormDesigner: "6.0.4.1.172" Java: "1.8.0_152-release" encoding: "UTF-8" 2 | 3 | new FormModel { 4 | contentType: "form/swing" 5 | root: new FormRoot { 6 | add( new FormWindow( "javax.swing.JFrame", new FormLayoutManager( class org.jdesktop.layout.GroupLayout ) { 7 | "$horizontalGroup": "par l {seq {par l {seq l {space :p:24:p, par l {seq {comp label1:::p::p, space u:::p, comp eField:::p:648:p}, seq l {par l {comp label2::l:p::p, comp label3::l:p::p, comp label4::l:p::p, comp label5::l:p:42:p}, space u:::p, par l {comp scrollPane1:::p:647:p, comp scrollPane2:::p:647:p, comp scrollPane::l:p:647:p, comp scrollPane4::l:p:647:p}}}}, seq l {space :p:242:p, comp encButton:::p::p, space :p:119:p, comp decButton:::p::p}}, space ::38:x}}" 8 | "$verticalGroup": "par l {seq l {space :p:18:p, par b {comp label1::b:p::p, comp eField::b:p::p}, space :p:30:p, par l {comp label2:::p::p, comp scrollPane1:::p:92:p}, space :p:34:p, par l {comp label3:::p::p, comp scrollPane2:::p:100:p}, par l {seq {space :p:38:p, comp label4:::p::p}, seq l {space :p:46:p, comp scrollPane:::p:100:p}}, space ::42:x, par l {comp label5:::p::p, comp scrollPane4:::p:100:p}, space :p:40:p, par b {comp decButton::b:p::p, comp encButton::b:p::p}, space :p:41:p}}" 9 | } ) { 10 | name: "this" 11 | "title": "RSA - jordonyang" 12 | add( new FormComponent( "javax.swing.JLabel" ) { 13 | name: "label1" 14 | "text": "公钥e" 15 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 16 | } ) 17 | add( new FormComponent( "javax.swing.JTextField" ) { 18 | name: "eField" 19 | "editable": false 20 | } ) 21 | add( new FormComponent( "javax.swing.JLabel" ) { 22 | name: "label2" 23 | "text": "私钥d" 24 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 25 | } ) 26 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 27 | name: "scrollPane1" 28 | add( new FormComponent( "javax.swing.JTextArea" ) { 29 | name: "dArea" 30 | "editable": false 31 | } ) 32 | } ) 33 | add( new FormComponent( "javax.swing.JLabel" ) { 34 | name: "label3" 35 | "text": "模n" 36 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 37 | } ) 38 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 39 | name: "scrollPane2" 40 | add( new FormComponent( "javax.swing.JTextArea" ) { 41 | name: "nArea" 42 | "editable": false 43 | } ) 44 | } ) 45 | add( new FormComponent( "javax.swing.JLabel" ) { 46 | name: "label4" 47 | "text": "明文" 48 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 49 | } ) 50 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 51 | name: "scrollPane" 52 | add( new FormComponent( "javax.swing.JTextArea" ) { 53 | name: "ptArea" 54 | } ) 55 | } ) 56 | add( new FormComponent( "javax.swing.JLabel" ) { 57 | name: "label5" 58 | "text": "密文" 59 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 60 | } ) 61 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 62 | name: "scrollPane4" 63 | add( new FormComponent( "javax.swing.JTextArea" ) { 64 | name: "cArea" 65 | } ) 66 | } ) 67 | add( new FormComponent( "javax.swing.JButton" ) { 68 | name: "encButton" 69 | "text": "加密" 70 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 71 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "encButtonActionPerformed", true ) ) 72 | } ) 73 | add( new FormComponent( "javax.swing.JButton" ) { 74 | name: "decButton" 75 | "text": "解密" 76 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 77 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decButtonActionPerformed", true ) ) 78 | } ) 79 | }, new FormLayoutConstraints( null ) { 80 | "location": new java.awt.Point( 10, 0 ) 81 | "size": new java.awt.Dimension( 765, 730 ) 82 | } ) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/RSAView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by JFormDesigner on Fri Nov 30 01:17:29 CST 2018 3 | */ 4 | 5 | package org.jordon.security.view; 6 | 7 | import org.jordon.security.core.crypto.assymmetry.RawRSACipherService; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | import java.awt.event.ActionEvent; 12 | 13 | /** 14 | * @author Jasion 15 | */ 16 | public class RSAView extends JFrame { 17 | 18 | private RawRSACipherService service = new RawRSACipherService(); 19 | 20 | public static void main(String[] args) { 21 | RSAView view = new RSAView(); 22 | view.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 23 | view.setLocationRelativeTo(null); 24 | view.setVisible(true); 25 | } 26 | 27 | public RSAView() { 28 | initComponents(); 29 | pField.setText(String.valueOf(service.getP())); 30 | qField.setText(String.valueOf(service.getQ())); 31 | nField.setText(String.valueOf(service.getN())); 32 | phiField.setText(String.valueOf(service.getEulerVal())); 33 | eField.setText(String.valueOf(service.getE())); 34 | dField.setText(String.valueOf(service.getD())); 35 | } 36 | 37 | // 加密按钮事件 38 | private void encButtonActionPerformed(ActionEvent e) { 39 | String plaintext = ptArea.getText(); 40 | cipherArea.setText(service.encrypt(plaintext)); 41 | } 42 | 43 | // 解密按钮事件 44 | private void decButtonActionPerformed(ActionEvent e) { 45 | String cipher = cipherArea.getText(); 46 | ptArea.setText(service.decrypt(cipher)); 47 | } 48 | 49 | private void initComponents() { 50 | // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents 51 | // Generated using JFormDesigner Evaluation license - Jasion 52 | encButton = new JButton(); 53 | decButton = new JButton(); 54 | label1 = new JLabel(); 55 | pField = new JTextField(); 56 | label2 = new JLabel(); 57 | qField = new JTextField(); 58 | label3 = new JLabel(); 59 | nField = new JTextField(); 60 | label4 = new JLabel(); 61 | phiField = new JTextField(); 62 | eField = new JTextField(); 63 | label5 = new JLabel(); 64 | label6 = new JLabel(); 65 | dField = new JTextField(); 66 | label7 = new JLabel(); 67 | scrollPane1 = new JScrollPane(); 68 | cipherArea = new JTextArea(); 69 | label8 = new JLabel(); 70 | scrollPane2 = new JScrollPane(); 71 | ptArea = new JTextArea(); 72 | 73 | //======== this ======== 74 | setTitle("RSA - jordonyang"); 75 | Container contentPane = getContentPane(); 76 | 77 | //---- encButton ---- 78 | encButton.setText("\u52a0\u5bc6"); 79 | encButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 80 | encButton.addActionListener(e -> encButtonActionPerformed(e)); 81 | 82 | //---- decButton ---- 83 | decButton.setText("\u89e3\u5bc6"); 84 | decButton.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 85 | decButton.addActionListener(e -> decButtonActionPerformed(e)); 86 | 87 | //---- label1 ---- 88 | label1.setText("p"); 89 | label1.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 90 | 91 | //---- pField ---- 92 | pField.setEditable(false); 93 | 94 | //---- label2 ---- 95 | label2.setText("q"); 96 | label2.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 97 | 98 | //---- qField ---- 99 | qField.setEditable(false); 100 | 101 | //---- label3 ---- 102 | label3.setText("n"); 103 | label3.setFont(new Font("Microsoft YaHei UI", Font.ITALIC, 16)); 104 | 105 | //---- nField ---- 106 | nField.setEditable(false); 107 | 108 | //---- label4 ---- 109 | label4.setText("\u03c6(n)"); 110 | label4.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 111 | 112 | //---- phiField ---- 113 | phiField.setEditable(false); 114 | 115 | //---- eField ---- 116 | eField.setEditable(false); 117 | 118 | //---- label5 ---- 119 | label5.setText("e"); 120 | label5.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 121 | 122 | //---- label6 ---- 123 | label6.setText("d"); 124 | label6.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 125 | 126 | //---- dField ---- 127 | dField.setEditable(false); 128 | 129 | //---- label7 ---- 130 | label7.setText("\u660e\u6587"); 131 | label7.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 132 | 133 | //======== scrollPane1 ======== 134 | { 135 | scrollPane1.setViewportView(cipherArea); 136 | } 137 | cipherArea.setLineWrap(true); // 激活自动换行功能 138 | cipherArea.setWrapStyleWord(true); // 激活断行不断字功能 139 | //---- label8 ---- 140 | label8.setText("\u5bc6\u6587"); 141 | label8.setFont(new Font("Microsoft YaHei UI", Font.PLAIN, 16)); 142 | 143 | //======== scrollPane2 ======== 144 | { 145 | scrollPane2.setViewportView(ptArea); 146 | } 147 | 148 | ptArea.setLineWrap(true); // 激活自动换行功能 149 | ptArea.setWrapStyleWord(true); // 激活断行不断字功能 150 | 151 | GroupLayout contentPaneLayout = new GroupLayout(contentPane); 152 | contentPane.setLayout(contentPaneLayout); 153 | contentPaneLayout.setHorizontalGroup( 154 | contentPaneLayout.createParallelGroup() 155 | .addGroup(contentPaneLayout.createSequentialGroup() 156 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) 157 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 495, GroupLayout.PREFERRED_SIZE) 158 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 495, GroupLayout.PREFERRED_SIZE) 159 | .addGroup(contentPaneLayout.createSequentialGroup() 160 | .addGroup(contentPaneLayout.createParallelGroup() 161 | .addGroup(contentPaneLayout.createSequentialGroup() 162 | .addGap(213, 213, 213) 163 | .addComponent(encButton) 164 | .addGap(38, 38, 38) 165 | .addComponent(decButton)) 166 | .addGroup(contentPaneLayout.createSequentialGroup() 167 | .addGap(25, 25, 25) 168 | .addGroup(contentPaneLayout.createParallelGroup() 169 | .addComponent(label7) 170 | .addGroup(contentPaneLayout.createSequentialGroup() 171 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) 172 | .addComponent(label1, GroupLayout.DEFAULT_SIZE, 22, Short.MAX_VALUE) 173 | .addComponent(label5, GroupLayout.DEFAULT_SIZE, 22, Short.MAX_VALUE)) 174 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 175 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) 176 | .addComponent(eField, GroupLayout.DEFAULT_SIZE, 56, Short.MAX_VALUE) 177 | .addComponent(pField, GroupLayout.DEFAULT_SIZE, 56, Short.MAX_VALUE)) 178 | .addGap(34, 34, 34) 179 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) 180 | .addComponent(label2, GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE) 181 | .addComponent(label6, GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE)) 182 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 183 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) 184 | .addComponent(qField, GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE) 185 | .addComponent(dField, GroupLayout.DEFAULT_SIZE, 63, Short.MAX_VALUE)) 186 | .addGap(42, 42, 42) 187 | .addComponent(label3, GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE) 188 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 189 | .addComponent(nField, GroupLayout.PREFERRED_SIZE, 66, GroupLayout.PREFERRED_SIZE) 190 | .addGap(45, 45, 45) 191 | .addComponent(label4) 192 | .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) 193 | .addComponent(phiField, GroupLayout.PREFERRED_SIZE, 77, GroupLayout.PREFERRED_SIZE)) 194 | .addComponent(label8, GroupLayout.PREFERRED_SIZE, 38, GroupLayout.PREFERRED_SIZE)))) 195 | .addGap(27, 27, 27))) 196 | .addContainerGap(44, Short.MAX_VALUE)) 197 | ); 198 | contentPaneLayout.setVerticalGroup( 199 | contentPaneLayout.createParallelGroup() 200 | .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup() 201 | .addGap(15, 15, 15) 202 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 203 | .addComponent(label1) 204 | .addComponent(pField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 205 | .addComponent(label2) 206 | .addComponent(qField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 207 | .addComponent(nField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 208 | .addComponent(label3) 209 | .addComponent(phiField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 210 | .addComponent(label4)) 211 | .addGap(18, 18, 18) 212 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 213 | .addComponent(eField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) 214 | .addComponent(label5) 215 | .addComponent(label6) 216 | .addComponent(dField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) 217 | .addGap(39, 39, 39) 218 | .addComponent(label7) 219 | .addGap(10, 10, 10) 220 | .addComponent(scrollPane2, GroupLayout.PREFERRED_SIZE, 137, GroupLayout.PREFERRED_SIZE) 221 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 32, Short.MAX_VALUE) 222 | .addComponent(label8, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE) 223 | .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) 224 | .addComponent(scrollPane1, GroupLayout.PREFERRED_SIZE, 151, GroupLayout.PREFERRED_SIZE) 225 | .addGap(36, 36, 36) 226 | .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 227 | .addComponent(encButton) 228 | .addComponent(decButton)) 229 | .addGap(19, 19, 19)) 230 | ); 231 | pack(); 232 | setLocationRelativeTo(getOwner()); 233 | // JFormDesigner - End of component initialization //GEN-END:initComponents 234 | } 235 | 236 | // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables 237 | // Generated using JFormDesigner Evaluation license - Jasion 238 | private JButton encButton; 239 | private JButton decButton; 240 | private JLabel label1; 241 | private JTextField pField; 242 | private JLabel label2; 243 | private JTextField qField; 244 | private JLabel label3; 245 | private JTextField nField; 246 | private JLabel label4; 247 | private JTextField phiField; 248 | private JTextField eField; 249 | private JLabel label5; 250 | private JLabel label6; 251 | private JTextField dField; 252 | private JLabel label7; 253 | private JScrollPane scrollPane1; 254 | private JTextArea cipherArea; 255 | private JLabel label8; 256 | private JScrollPane scrollPane2; 257 | private JTextArea ptArea; 258 | // JFormDesigner - End of variables declaration //GEN-END:variables 259 | } 260 | -------------------------------------------------------------------------------- /src/main/java/org/jordon/security/view/RSAView.jfd: -------------------------------------------------------------------------------- 1 | JFDML JFormDesigner: "6.0.4.1.172" Java: "1.8.0_152-release" encoding: "UTF-8" 2 | 3 | new FormModel { 4 | contentType: "form/swing" 5 | root: new FormRoot { 6 | add( new FormWindow( "javax.swing.JFrame", new FormLayoutManager( class org.jdesktop.layout.GroupLayout ) { 7 | "$horizontalGroup": "par l {seq l {par t {comp scrollPane1:::p:495:p, comp scrollPane2:::p:495:p, seq {par l {seq l {space :p:213:p, comp encButton:::p::p, space :p:38:p, comp decButton:::p::p}, seq l {space :p:25:p, par l {comp label7:::p::p, seq l {par l:::p {comp label1::::22:x, comp label5::::22:x}, space :::p, par l:::p {comp eField::::56:x, comp pField::::56:x}, space :p:34:p, par l:::p {comp label2::::24:x, comp label6::::24:x}, space :::p, par l:::p {comp qField::::63:x, comp dField::::63:x}, space :p:42:p, comp label3:::p:21:p, space :::p, comp nField:::p:66:p, space :p:45:p, comp label4:::p::p, space u:::p, comp phiField:::p:77:p}, comp label8::l:p:38:p}}}, space :p:27:p}}, space ::44:x}}" 8 | "$verticalGroup": "par l {seq t {space :p:15:p, par b {comp label1::b:p::p, comp pField::b:p::p, comp label2::b:p::p, comp qField::b:p::p, comp nField::b:p::p, comp label3::b:p::p, comp phiField::b:p::p, comp label4::b:p::p}, space s:::p, par b {comp eField::b:p::p, comp label5::b:p::p, comp label6::b:p::p, comp dField::b:p::p}, space :p:39:p, comp label7:::p::p, space :p:10:p, comp scrollPane2:::p:137:p, space ::32:x, comp label8:::p:23:p, space :::p, comp scrollPane1:::p:151:p, space :p:36:p, par b {comp encButton::b:p::p, comp decButton::b:p::p}, space :p:19:p}}" 9 | } ) { 10 | name: "this" 11 | "title": "RSA - jordonyang" 12 | add( new FormComponent( "javax.swing.JButton" ) { 13 | name: "encButton" 14 | "text": "加密" 15 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 16 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "encButtonActionPerformed", true ) ) 17 | } ) 18 | add( new FormComponent( "javax.swing.JButton" ) { 19 | name: "decButton" 20 | "text": "解密" 21 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 22 | addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decButtonActionPerformed", true ) ) 23 | } ) 24 | add( new FormComponent( "javax.swing.JLabel" ) { 25 | name: "label1" 26 | "text": "p" 27 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 28 | } ) 29 | add( new FormComponent( "javax.swing.JTextField" ) { 30 | name: "pField" 31 | "editable": false 32 | } ) 33 | add( new FormComponent( "javax.swing.JLabel" ) { 34 | name: "label2" 35 | "text": "q" 36 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 37 | } ) 38 | add( new FormComponent( "javax.swing.JTextField" ) { 39 | name: "qField" 40 | "editable": false 41 | } ) 42 | add( new FormComponent( "javax.swing.JLabel" ) { 43 | name: "label3" 44 | "text": "n" 45 | "font": new java.awt.Font( "Microsoft YaHei UI", 2, 16 ) 46 | } ) 47 | add( new FormComponent( "javax.swing.JTextField" ) { 48 | name: "nField" 49 | "editable": false 50 | } ) 51 | add( new FormComponent( "javax.swing.JLabel" ) { 52 | name: "label4" 53 | "text": "φ(n)" 54 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 55 | } ) 56 | add( new FormComponent( "javax.swing.JTextField" ) { 57 | name: "phiField" 58 | "editable": false 59 | } ) 60 | add( new FormComponent( "javax.swing.JTextField" ) { 61 | name: "eField" 62 | "editable": false 63 | } ) 64 | add( new FormComponent( "javax.swing.JLabel" ) { 65 | name: "label5" 66 | "text": "e" 67 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 68 | } ) 69 | add( new FormComponent( "javax.swing.JLabel" ) { 70 | name: "label6" 71 | "text": "d" 72 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 73 | } ) 74 | add( new FormComponent( "javax.swing.JTextField" ) { 75 | name: "dField" 76 | "editable": false 77 | } ) 78 | add( new FormComponent( "javax.swing.JLabel" ) { 79 | name: "label7" 80 | "text": "明文" 81 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 82 | } ) 83 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 84 | name: "scrollPane1" 85 | add( new FormComponent( "javax.swing.JTextArea" ) { 86 | name: "cipherArea" 87 | } ) 88 | } ) 89 | add( new FormComponent( "javax.swing.JLabel" ) { 90 | name: "label8" 91 | "text": "密文" 92 | "font": new java.awt.Font( "Microsoft YaHei UI", 0, 16 ) 93 | } ) 94 | add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) { 95 | name: "scrollPane2" 96 | add( new FormComponent( "javax.swing.JTextArea" ) { 97 | name: "ptArea" 98 | } ) 99 | } ) 100 | }, new FormLayoutConstraints( null ) { 101 | "location": new java.awt.Point( 40, 5 ) 102 | "size": new java.awt.Dimension( 610, 620 ) 103 | } ) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/AppTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.jordon.security.core.crypto.CipherService; 6 | import org.jordon.security.core.crypto.symmetry.DESCipherService; 7 | import org.junit.Test; 8 | 9 | import java.io.UnsupportedEncodingException; 10 | import java.util.Arrays; 11 | import java.util.Random; 12 | 13 | /** 14 | * Unit test for simple App. 15 | */ 16 | public class AppTest { 17 | 18 | @Test 19 | public void testService() { 20 | String plaintext = "01234567", key = "12345678"; 21 | CipherService cipherService = new DESCipherService(false); 22 | try { 23 | String encryptedText = cipherService.encrypt(plaintext, key); 24 | cipherService.decrypt(encryptedText,key); 25 | } catch (UnsupportedEncodingException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | /** 31 | * Rigorous Test :-) 32 | */ 33 | @Test 34 | public void shouldAnswerWithTrue() { 35 | assertTrue( true ); 36 | } 37 | 38 | @Test 39 | public void testGCD() { 40 | Random random = new Random(); 41 | int[] ranges = {10, 100, 1000, 10000, 100000, Integer.MAX_VALUE}; 42 | for (int range : ranges) { 43 | for (int i = 0; i < 1000; i++) { 44 | int m = random.nextInt(range); 45 | int n = random.nextInt(range); 46 | if (m == 0 && n == 0) 47 | continue; 48 | System.out.println(String.format("%-50s%-50s%-50s", m, n, gcd(m, n))); 49 | } 50 | } 51 | } 52 | 53 | private static int gcd(int m, int n) { 54 | if (m == 0 || n == 0) 55 | return 0; 56 | while(true){ 57 | if ((m = m % n) == 0) 58 | return n; 59 | if ((n = n % m) == 0) 60 | return m; 61 | } 62 | } 63 | 64 | @Test 65 | public void testIsPrime() { 66 | Random random = new Random(); 67 | int[] ranges = {10, 100, 1000, 10000, 100000, Integer.MAX_VALUE}; 68 | for (int range : ranges) { 69 | for (int i = 0; i < 1000; i++) { 70 | int m = random.nextInt(range); 71 | if (m < 2) 72 | continue; 73 | System.out.println(String.format("%-50s%-50s", m, isPrime(m))); 74 | } 75 | } 76 | } 77 | 78 | private boolean isPrime(int a) { 79 | boolean isPrime = true; 80 | for(int i = 2 ; i <= Math.sqrt(a) ; i++){ 81 | //Math.sqrt 是调用Math类中的sqrt方法,求一个数的平方根 82 | if(a % i == 0){ 83 | isPrime = false; 84 | break; 85 | } 86 | } 87 | return isPrime; 88 | } 89 | 90 | private static long[] ex_gcd(long a, long b) { 91 | long ans; 92 | long[] result = new long[3]; 93 | if(b == 0) { 94 | result[0] = a; 95 | result[1] = 1; 96 | result[2] = 0; 97 | return result; 98 | } 99 | long [] temp = ex_gcd(b,a % b); 100 | ans = temp[0]; 101 | result[0] = ans; 102 | result[1] = temp[2]; 103 | result[2] = temp[1] - (a / b) * temp[2]; 104 | return result; 105 | } 106 | 107 | 108 | private int ModExp(int b, int n, int m){ 109 | int exponent = 1; 110 | for (int i = 0; i < n ;i++) { 111 | exponent *= b; 112 | } 113 | return exponent % m; 114 | } 115 | 116 | @Test 117 | public void test() { 118 | char[] chars = new char[3]; 119 | chars[0] = '1'; 120 | chars[2] = 'i'; 121 | System.out.println(Arrays.toString(chars)); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/ByteTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security; 2 | import org.jordon.security.util.ArrayUtil; 3 | import org.junit.Test; 4 | import java.util.Arrays; 5 | 6 | public class ByteTest { 7 | 8 | @Test 9 | public void testXor() { 10 | char[] a = {'0', '0', '1', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '1', '0', '0', 11 | '0', '0', '1', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '1', '0', '0', 12 | '0', '0', '1', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1', '1', '0', '0'}; 13 | 14 | char[] b = {'1', '1', '0', '0', '1', '1', 15 | '0', '0', '0', '0', '1', '1', 16 | '1', '1', '0', '0', '0', '0', 17 | '1', '1', '1', '1', '0', '0', 18 | '0', '0', '1', '1', '1', '1', 19 | '0', '0', '0', '0', '1', '1', 20 | '1', '1', '0', '0', '0', '0', 21 | '1', '1', '1', '0', '1', '1'}; 22 | 23 | char[] xorResult = ArrayUtil.xor(a, b, 48); 24 | ArrayUtil.printArray(xorResult); 25 | System.out.println(Arrays.deepToString(ArrayUtil.segmentDimension(b, 8, 6))); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/RSATest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security; 2 | 3 | import org.junit.Test; 4 | 5 | import java.math.BigInteger; 6 | import java.util.Random; 7 | 8 | public class RSATest { 9 | 10 | @Test 11 | public void test() { 12 | long begin = System.currentTimeMillis(); 13 | BigInteger bigInteger = BigInteger.probablePrime(1024, new Random()); 14 | long end = System.currentTimeMillis(); 15 | System.out.println((bigInteger.add(new BigInteger("-1"))).isProbablePrime(Integer.MAX_VALUE)); 16 | System.out.println((end - begin) + " milliseconds spent"); 17 | System.out.println(bigInteger.toString(2)); 18 | } 19 | 20 | @Test 21 | public void testM() { 22 | BigInteger a = new BigInteger("4").pow(2).mod(new BigInteger("6")); 23 | 24 | System.out.println(a.toString(10)); 25 | } 26 | 27 | @Test 28 | public void tes() { 29 | 30 | int[] as = {3337, 688, 232, 687, 966, 668}; 31 | for (int i : as) { 32 | System.out.println(Integer.toBinaryString(i).length()); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/core/CipherServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core; 2 | 3 | import org.jordon.security.core.crypto.CipherService; 4 | import org.jordon.security.core.crypto.symmetry.AESCipherService; 5 | import org.jordon.security.core.crypto.symmetry.DESCipherService; 6 | import org.jordon.security.util.ArrayUtil; 7 | import org.junit.Test; 8 | 9 | import java.io.UnsupportedEncodingException; 10 | import java.math.BigInteger; 11 | 12 | public class CipherServiceTest { 13 | 14 | @Test 15 | public void testAES() throws UnsupportedEncodingException { 16 | String plaintext = "passwordTextCase", key = "simpleKeyCase123"; 17 | CipherService aesService = new AESCipherService(); 18 | String encryptedText = aesService.encrypt(plaintext, key); 19 | 20 | ArrayUtil.printInfo("encrypted text", encryptedText, false); 21 | aesService.decrypt(encryptedText, key); 22 | } 23 | 24 | @Test 25 | public void testDESService() throws UnsupportedEncodingException { 26 | String plaintext = "01234567", key = "12345678"; 27 | CipherService desService = new DESCipherService(false); 28 | String encryptedText = desService.encrypt(plaintext, key); 29 | 30 | desService.decrypt(encryptedText,key); 31 | } 32 | 33 | @Test 34 | public void t() { 35 | // extendedEuclid(3337, 547); 36 | extendedEuclid(new BigInteger("3337"), new BigInteger("547")); 37 | } 38 | 39 | private void extendedEuclid(long a, long b) { 40 | long x = 0, y = 1, lastX = 1, lastY = 0, temp; 41 | while (b != 0) 42 | { 43 | long q = a / b; 44 | long r = a % b; 45 | 46 | a = b; 47 | b = r; 48 | 49 | temp = x; 50 | x = lastX - q * x; 51 | lastX = temp; 52 | 53 | temp = y; 54 | y = lastY - q * y; 55 | lastY = temp; 56 | } 57 | System.out.println("Roots x : " + lastX + " y :" + lastY); 58 | } 59 | 60 | /** 61 | * 扩展欧几里得非递归实现 62 | * @param a 操作数 63 | * @param b 操作数 64 | */ 65 | private void extendedEuclid(BigInteger a, BigInteger b) { 66 | BigInteger x = BigInteger.ZERO, y = BigInteger.ONE, 67 | lastX = BigInteger.ONE, lastY = BigInteger.ZERO, temp; 68 | 69 | if (a.compareTo(b) < 0) { 70 | temp = a; 71 | a = b; 72 | b = temp; 73 | } 74 | 75 | while (!b.equals(BigInteger.ZERO)) { 76 | BigInteger q = a.divide(b); 77 | BigInteger r = a.mod(b); 78 | 79 | a = b; 80 | b = r; 81 | 82 | temp = x; 83 | x = lastX.subtract(q.multiply(x)); 84 | lastX = temp; 85 | 86 | temp = y; 87 | y = lastY.subtract(q.multiply(y)); 88 | lastY = temp; 89 | } 90 | System.out.println("Roots x : " + lastX.toString(10) + " y :" + 91 | lastY.toString(10)); 92 | } 93 | } -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/core/DESCipherServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core; 2 | 3 | import org.jordon.security.attack.cryptanalysis.DESDifferential; 4 | import org.jordon.security.attack.statistics.DESStatistics; 5 | import org.jordon.security.core.crypto.symmetry.DESCipherService; 6 | import org.jordon.security.util.ArrayUtil; 7 | import org.junit.Test; 8 | 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | import java.io.UnsupportedEncodingException; 12 | import java.util.Random; 13 | 14 | public class DESCipherServiceTest { 15 | 16 | /** 17 | * DES差分攻击 18 | */ 19 | @Test 20 | public void testDESDifferential() { 21 | DESDifferential desDifferential = new DESDifferential((short) 1); 22 | desDifferential.analyze(); 23 | } 24 | 25 | /** 26 | * 简单分析DES明文/密钥变化与密文变化位数的统计学关系 27 | */ 28 | @Test 29 | public void testDESStatistics() { 30 | DESStatistics desStatistics = new DESStatistics(10); 31 | desStatistics.run(); 32 | } 33 | 34 | @Test 35 | public void testPadPlaintext() { 36 | DESCipherService desCipherService = new DESCipherService(false); 37 | // desCipherService.padPlaintext("password1"); 38 | } 39 | 40 | @Test 41 | public void testEncryptFile() { 42 | DESCipherService desCipherService = new DESCipherService(false); 43 | desCipherService.setWorkingMode("ECB"); 44 | File file = new File("E:\\linfeng\\themes\\hugo-theme-casper" + 45 | "\\layouts\\partials\\twitter_card.html"); 46 | try { 47 | System.out.println(desCipherService.encryptFile(file, "password"));; 48 | } catch (UnsupportedEncodingException | FileNotFoundException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/core/RC4CipherServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core; 2 | 3 | import org.jordon.security.core.crypto.symmetry.RC4CipherService; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.Random; 8 | 9 | 10 | public class RC4CipherServiceTest { 11 | 12 | @Test 13 | public void test() { 14 | RC4CipherService rc4CipherService = new RC4CipherService(); 15 | String encryptedText = rc4CipherService.encrypt("password", "jason"); 16 | System.out.println(encryptedText); 17 | 18 | String decryptedText = rc4CipherService.decrypt(encryptedText, "jason"); 19 | System.out.println(decryptedText); 20 | } 21 | 22 | @Test 23 | public void testRan() { 24 | Random random = new Random(); 25 | for (int i = 0; i < 10; i++) { 26 | System.out.println(random.nextInt(4 - 2) + 2);; 27 | } 28 | } 29 | 30 | @Test 31 | public void test1() { 32 | String s = "测试测试"; 33 | char[] chars = s.toCharArray(); 34 | System.out.println(Arrays.toString(chars)); 35 | for (char c : chars) { 36 | System.out.println((int)c); 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/core/crypto/assymmetry/RSACipherServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.assymmetry; 2 | 3 | import org.junit.Test; 4 | 5 | import java.math.BigInteger; 6 | import java.security.SecureRandom; 7 | 8 | public class RSACipherServiceTest { 9 | private RSACipherService service = new RSACipherService(2 << 10); 10 | private final static SecureRandom random = new SecureRandom(); 11 | 12 | @Test 13 | public void test() { 14 | int N = 1024; 15 | RSACipherService key = new RSACipherService(N); 16 | System.out.println(key); 17 | 18 | // create random message, encrypt and decrypt 19 | BigInteger message = new BigInteger(N - 1, random); 20 | 21 | BigInteger encrypt = key.encrypt(message); 22 | BigInteger decrypt = key.decrypt(encrypt); 23 | System.out.println("message = " + message); 24 | System.out.println("encrypted = " + encrypt); 25 | System.out.println("decrypted = " + decrypt); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/org/jordon/security/core/crypto/assymmetry/RawRSACipherServiceTest.java: -------------------------------------------------------------------------------- 1 | package org.jordon.security.core.crypto.assymmetry; 2 | 3 | import org.jordon.security.util.ArrayUtil; 4 | import org.junit.Test; 5 | 6 | import java.util.Random; 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | public class RawRSACipherServiceTest { 10 | private Random random = ThreadLocalRandom.current(); 11 | 12 | @Test 13 | public void test() { 14 | RawRSACipherService service = new RawRSACipherService(); 15 | for (int i = 0; i < 30; i++) { // 进行30次测试 16 | String example = genPlaintext(); 17 | ArrayUtil.printInfo("example", example, false); 18 | String cipher = service.encrypt(example); 19 | ArrayUtil.printInfo("cipher", cipher, false); 20 | String plaintext = service.decrypt(cipher); 21 | ArrayUtil.printInfo("plaintext", plaintext, true); 22 | } 23 | } 24 | 25 | // 随机生成明文样例 26 | private String genPlaintext() { 27 | // 随机生成含有[1, 50]个可打印字符的字符串 28 | int count = random.nextInt(20) + 1; 29 | StringBuilder builder = new StringBuilder(); 30 | for (int i = 0; i < count; i++) { 31 | // 在可打印字符范围内随机获取 32 | int val = random.nextInt(126 -33) + 33; 33 | builder.append((char) val); 34 | } 35 | return builder.toString(); 36 | } 37 | } --------------------------------------------------------------------------------