├── .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 | }
--------------------------------------------------------------------------------