本文主要是介绍Java GUI + exe4j制作加解密桌面程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
效果图
技术选择
1.创建Maven项目而非普通Java项目;
方便引入依赖,后期打包时将其它依赖一并打入jar中;
2.安装exe4j将jar文件转换成exe可执行文件;
3.JDK1.8
代码
1.项目结构
客户端访问平台数据格式
{"requestTime": "2023-12-26 15:40:44","data": "","sign": ""
}
平台响应客户端数据格式
{"data":"","requestTime": "2023-12-26 15:40:44","code": "200","message": "","responseTime": "2023-12-26 17:12:20","sign":""
}
2.pom依赖
因为是单机程序不是Web所以不用导入Web相关依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.0</version></parent><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.7</version></dependency><dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId><version>1.10</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.78</version></dependency></dependencies>
3.加解密工具类
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @Description: 支持AES、DES、RSA加密、数字签名以及生成对称密钥和非对称密钥对*/
public class Crypto {private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;private static final Encoder BASE64_ENCODER = Base64.getEncoder();private static final Decoder BASE64_DECODER = Base64.getDecoder();private static final Map<Algorithm, KeyFactory> KEY_FACTORY_CACHE = new ConcurrentHashMap<>();private static final Map<Algorithm, Cipher> CIPHER_CACHE = new HashMap<>();/*** 生成对称密钥,目前支持的算法有AES、DES* @param algorithm* @return* @throws NoSuchAlgorithmException*/public static String generateSymmetricKey(Algorithm algorithm) throws NoSuchAlgorithmException {KeyGenerator generator = KeyGenerator.getInstance(algorithm.getName());generator.init(algorithm.getKeySize());SecretKey secretKey = generator.generateKey();return BASE64_ENCODER.encodeToString(secretKey.getEncoded());}/*** 生成非对称密钥对,目前支持的算法有RSA、DSA。备注:默认生成的密钥格式为PKCS8* @param algorithm* @return* @throws NoSuchAlgorithmException*/public static AsymmetricKeyPair generateAsymmetricKeyPair(Algorithm algorithm) throws NoSuchAlgorithmException {KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm.getName());generator.initialize(algorithm.getKeySize());KeyPair keyPair = generator.generateKeyPair();String publicKey = BASE64_ENCODER.encodeToString(keyPair.getPublic().getEncoded());String privateKey = BASE64_ENCODER.encodeToString(keyPair.getPrivate().getEncoded());return new AsymmetricKeyPair(publicKey, privateKey);}/*** SHA1签名算法和DSA加密算法结合使用生成数字签名* @param privateKeyText* @param msg* @return 数字签名* @throws Exception*/public static String signBySHA1WithDSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Algorithm.Encryption.DSA, Algorithm.Signing.SHA1WithDSA);}/*** SHA1签名算法和RSA加密算法结合使用生成数字签名* @param privateKeyText 私钥* @param msg 待加签内容* @return 数字签名* @throws Exception*/public static String signBySHA1WithRSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Algorithm.Encryption.RSA_ECB_PKCS1, Algorithm.Signing.SHA1WithRSA);}/*** SHA256签名算法和RSA加密算法结合使用生成数字签名* @param privateKeyText 私钥* @param msg 待加签内容* @return 数字签名* @throws Exception*/public static String signBySHA256WithRSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Algorithm.Encryption.RSA_ECB_PKCS1, Algorithm.Signing.SHA256WithRSA);}/*** SHA1签名算法和DSA加密算法检验数字签名* @param publicKeyText 公钥* @param msg 待验签内容* @param signatureText 数字* @return 检验是否成功* @throws Exception*/public static boolean verifyBySHA1WithDSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Algorithm.Encryption.DSA, Algorithm.Signing.SHA1WithDSA);}/*** SHA1签名算法和RSA加密算法检验数字签名* @param publicKeyText 公钥* @param msg 待验签内容* @param signatureText 签名* @return 校验是否成功* @throws Exception*/public static boolean verifyBySHA1WithRSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Algorithm.Encryption.RSA_ECB_PKCS1, Algorithm.Signing.SHA1WithRSA);}/*** SHA256签名算法和RSA加密算法检验数字签名* @param publicKeyText 公钥* @param msg 待验签内容* @param signatureText 签名* @return 校验是否成功* @throws Exception*/public static boolean verifyBySHA256WithRSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Algorithm.Encryption.RSA_ECB_PKCS1, Algorithm.Signing.SHA256WithRSA);}/*** 对称加密* @param secretKey 密钥* @param iv 加密向量,只有CBC模式才支持,如果是CBC则必传* @param plainText 明文* @param algorithm 对称加密算法,如AES、DES* @return* @throws Exception*/public static String encryptSymmetrically(String secretKey, String iv, String plainText, Algorithm algorithm) throws Exception {SecretKey key = decodeSymmetricKey(secretKey, algorithm);IvParameterSpec ivParameterSpec = StringUtils.isBlank(iv) ? null : decodeIv(iv);byte[] plainTextInBytes = plainText.getBytes(DEFAULT_CHARSET);byte[] ciphertextInBytes = transform(algorithm, Cipher.ENCRYPT_MODE, key, ivParameterSpec, plainTextInBytes);return BASE64_ENCODER.encodeToString(ciphertextInBytes);}/*** 对称解密* @param secretKey 密钥* @param iv 加密向量,只有CBC模式才支持,如果是CBC则必传* @param ciphertext 密文* @param algorithm 对称加密算法,如AES、DES* @return* @throws Exception*/public static String decryptSymmetrically(String secretKey, String iv, String ciphertext, Algorithm algorithm) throws Exception {SecretKey key = decodeSymmetricKey(secretKey, algorithm);IvParameterSpec ivParameterSpec = StringUtils.isBlank(iv) ? null : decodeIv(iv);byte[] ciphertextInBytes = BASE64_DECODER.decode(ciphertext);byte[] plainTextInBytes = transform(algorithm, Cipher.DECRYPT_MODE, key, ivParameterSpec, ciphertextInBytes);return new String(plainTextInBytes, DEFAULT_CHARSET);}/*** 非对称加密* @param publicKeyText 公钥* @param plainText 明文* @param algorithm 非对称加密算法* @return* @throws Exception*/public static String encryptAsymmetrically(String publicKeyText, String plainText, Algorithm algorithm) throws Exception {PublicKey publicKey = regeneratePublicKey(publicKeyText, algorithm);byte[] plainTextInBytes = plainText.getBytes(DEFAULT_CHARSET);byte[] ciphertextInBytes = transform(algorithm, Cipher.ENCRYPT_MODE, publicKey, plainTextInBytes);return BASE64_ENCODER.encodeToString(ciphertextInBytes);}/*** 非对称解密* @param privateKeyText 私钥* @param ciphertext 密文* @param algorithm 非对称加密算法* @return* @throws Exception*/public static String decryptAsymmetrically(String privateKeyText, String ciphertext, Algorithm algorithm) throws Exception {PrivateKey privateKey = regeneratePrivateKey(privateKeyText, algorithm);byte[] ciphertextInBytes = BASE64_DECODER.decode(ciphertext);byte[] plainTextInBytes = transform(algorithm, Cipher.DECRYPT_MODE, privateKey, ciphertextInBytes);return new String(plainTextInBytes, DEFAULT_CHARSET);}/*** 生成数字签名* @param privateKeyText 私钥* @param msg 传输的数据* @param encryptionAlgorithm 加密算法,见Algorithm中的加密算法* @param signatureAlgorithm 签名算法,见Algorithm中的签名算法* @return 数字签名* @throws Exception*/public static String doSign(String privateKeyText, String msg, Algorithm encryptionAlgorithm, Algorithm signatureAlgorithm)throws Exception {PrivateKey privateKey = regeneratePrivateKey(privateKeyText, encryptionAlgorithm);// Signature只支持签名算法Signature signature = Signature.getInstance(signatureAlgorithm.getName());signature.initSign(privateKey);signature.update(msg.getBytes(DEFAULT_CHARSET));byte[] signatureInBytes = signature.sign();return BASE64_ENCODER.encodeToString(signatureInBytes);}/*** 数字签名验证* @param publicKeyText 公钥* @param msg 传输的数据* @param signatureText 数字签名* @param encryptionAlgorithm 加密算法,见Algorithm中的加密算法* @param signatureAlgorithm 签名算法,见Algorithm中的签名算法* @return 校验是否成功* @throws Exception*/public static boolean doVerify(String publicKeyText, String msg, String signatureText, Algorithm encryptionAlgorithm,Algorithm signatureAlgorithm) throws Exception {PublicKey publicKey = regeneratePublicKey(publicKeyText, encryptionAlgorithm);Signature signature = Signature.getInstance(signatureAlgorithm.getName());signature.initVerify(publicKey);signature.update(msg.getBytes(DEFAULT_CHARSET));return signature.verify(BASE64_DECODER.decode(signatureText));}/*** 将密钥进行Base64位解码,重新生成SecretKey实例* @param secretKey 密钥* @param algorithm 算法* @return*/private static SecretKey decodeSymmetricKey(String secretKey, Algorithm algorithm) {byte[] key = BASE64_DECODER.decode(secretKey);return new SecretKeySpec(key, algorithm.getName());}private static IvParameterSpec decodeIv(String iv) {byte[] ivInBytes = BASE64_DECODER.decode(iv);return new IvParameterSpec(ivInBytes);}private static PublicKey regeneratePublicKey(String publicKeyText, Algorithm algorithm)throws NoSuchAlgorithmException, InvalidKeySpecException {byte[] keyInBytes = BASE64_DECODER.decode(publicKeyText);KeyFactory keyFactory = getKeyFactory(algorithm);// 公钥必须使用RSAPublicKeySpec或者X509EncodedKeySpecKeySpec publicKeySpec = new X509EncodedKeySpec(keyInBytes);PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);return publicKey;}private static PrivateKey regeneratePrivateKey(String key, Algorithm algorithm) throws Exception {byte[] keyInBytes = BASE64_DECODER.decode(key);KeyFactory keyFactory = getKeyFactory(algorithm);// 私钥必须使用RSAPrivateCrtKeySpec或者PKCS8EncodedKeySpecKeySpec privateKeySpec = new PKCS8EncodedKeySpec(keyInBytes);PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);return privateKey;}private static KeyFactory getKeyFactory(Algorithm algorithm) throws NoSuchAlgorithmException {KeyFactory keyFactory = KEY_FACTORY_CACHE.get(algorithm);if (keyFactory == null) {keyFactory = KeyFactory.getInstance(algorithm.getName());KEY_FACTORY_CACHE.put(algorithm, keyFactory);}return keyFactory;}private static byte[] transform(Algorithm algorithm, int mode, Key key, byte[] msg) throws Exception {return transform(algorithm, mode, key, null, msg);}private static byte[] transform(Algorithm algorithm, int mode, Key key, IvParameterSpec iv, byte[] msg) throws Exception {Cipher cipher = CIPHER_CACHE.get(algorithm);// double check,减少上下文切换if (cipher == null) {synchronized (CryptoUtils.class) {if ((cipher = CIPHER_CACHE.get(algorithm)) == null) {cipher = determineWhichCipherToUse(algorithm);CIPHER_CACHE.put(algorithm, cipher);}cipher.init(mode, key, iv);return cipher.doFinal(msg);}}synchronized (CryptoUtils.class) {cipher.init(mode, key, iv);return cipher.doFinal(msg);}}private static Cipher determineWhichCipherToUse(Algorithm algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {Cipher cipher;String transformation = algorithm.getTransformation();// 官方推荐的transformation使用algorithm/mode/padding组合,SunJCE使用ECB作为默认模式,使用PKCS5Padding作为默认填充if (StringUtils.isNotEmpty(transformation)) {cipher = Cipher.getInstance(transformation);} else {cipher = Cipher.getInstance(algorithm.getName());}return cipher;}/*** 算法分为加密算法和签名算法,更多算法实现见:<br/>* <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">jdk8中的标准算法</a>*/public static class Algorithm {public interface Encryption {Algorithm AES_ECB_PKCS5 = new Algorithm("AES", "AES/ECB/PKCS5Padding", 128);Algorithm AES_CBC_PKCS5 = new Algorithm("AES", "AES/CBC/PKCS5Padding", 128);Algorithm DES_ECB_PKCS5 = new Algorithm("DES", "DES/ECB/PKCS5Padding", 56);Algorithm DES_CBC_PKCS5 = new Algorithm("DES", "DES/CBC/PKCS5Padding", 56);Algorithm RSA_ECB_PKCS1 = new Algorithm("RSA", "RSA/ECB/PKCS1Padding", 1024);Algorithm DSA = new Algorithm("DSA", 1024);}public interface Signing {Algorithm SHA1WithDSA = new Algorithm("SHA1withDSA", 1024);Algorithm SHA1WithRSA = new Algorithm("SHA1WithRSA", 2048);Algorithm SHA256WithRSA = new Algorithm("SHA256WithRSA", 2048);}@Getterprivate String name;@Getterprivate String transformation;@Getterprivate int keySize;public Algorithm(String name, int keySize) {this(name, null, keySize);}public Algorithm(String name, String transformation, int keySize) {this.name = name;this.transformation = transformation;this.keySize = keySize;}}@Data@NoArgsConstructor@AllArgsConstructorpublic static class AsymmetricKeyPair {private String publicKey;private String privateKey;}
}
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;/*** @Description: Rsa加解密*/
public class Rsa {private static final String ALGORITHM = "RSA";//private static final String ALGORITHM = "RSA/ECB/PKCS1Padding";private static final String UTF8 = StandardCharsets.UTF_8.name();/*** rsa单次最大加密的文明大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/*** rsa单次最大解密的密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 生成经过base64编码后的密钥对(公钥和私钥)并存储在文件中*/public Map<String,String> getPriAndPubKey() throws Exception{KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(1024);//通过keyPair生成器生成keyPairKeyPair keyPair = keyPairGenerator.generateKeyPair();/*公钥*/PublicKey publicKey = keyPair.getPublic();//把对象转成字节数组byte[] encoded = publicKey.getEncoded();String publicKeyBase64Stri = Base64.encodeBase64String(encoded);//String publicKeyBase64Stri = new ByteFromStr().convertBytes2HexStr(encoded);/*私钥*/PrivateKey privateKey = keyPair.getPrivate();//把对象转成字节数组byte[] privateKeyEncoded = privateKey.getEncoded();String privateKeyBase64Stri = Base64.encodeBase64String(privateKeyEncoded);HashMap<String, String> hashMap = new HashMap<>();hashMap.put("public",publicKeyBase64Stri);hashMap.put("private",privateKeyBase64Stri);return hashMap;}/*** 从生成好的公钥文件rsa.pub(这里的公钥文件是通过Base64编码之后存储的数据)获取公钥对象* @return*/public PublicKey getPulickey(String publicKeyStr)throws Exception{//base64解码,获取字节数组byte[] decodeBase64 = Base64.decodeBase64(publicKeyStr);//传入算法名字”RAS“KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);//传入key的规则,对于公钥的规则就是x509,将公钥的字符串传入公钥规则里面X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decodeBase64);return keyFactory.generatePublic(x509EncodedKeySpec);}/*** 从生成好的私钥文件rsa.pri(这里的公钥文件是通过Base64编码之后存储的数据)获取私钥对象* @return*/public PrivateKey getPrivateKey(String privateKeyStr)throws Exception{//base64解码,获取字节数组byte[] decodeBase64 = Base64.decodeBase64(privateKeyStr);//传入算法名字”RAS“KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);//传入key的规则,对于私钥的规则就是PKCS8,将公钥的字符串传入公钥规则里面PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(decodeBase64);return keyFactory.generatePrivate(pkcs8EncodedKeySpec);}/*** 加密* @param originalCont 原始内容* @param key 公钥或者私钥* @return base64编码后的加密内容* @throws Exception*/public String encrypt(String originalCont, Key key) throws Exception{Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE,key);byte[] bytes = doCodec(cipher,originalCont.getBytes(UTF8),MAX_ENCRYPT_BLOCK);return Base64.encodeBase64String(bytes);}/*** 解密* @param encryptedStr 加密后内容* @param key 公钥或者私钥* @return 原始内容* @throws Exception*/public String decrypt(String encryptedStr, Key key) throws Exception{try {byte[] decodeBase64 = Base64.decodeBase64(encryptedStr);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE,key);byte[] decryptedBytes = doCodec(cipher,decodeBase64,MAX_DECRYPT_BLOCK);return new String(decryptedBytes);}catch (Exception e){e.printStackTrace();
// throw new AuthenticationServiceException("参数解密异常:"+e.getMessage());throw new RuntimeException("参数解密异常");}}/*** 执行加密或者解密* @param cipher* @param decodeBase64* @param maxDecryptBlock* @return*/private byte[] doCodec(Cipher cipher, byte[] decodeBase64, int maxDecryptBlock) throws Exception{//获取字节长度int inputLen = decodeBase64.length;//迁移量int offset = 0;//本次完成加密之后的数组byte[] cache;//循环的次数int i= 0;//ByteArrayOutputStream baos = new ByteArrayOutputStream();while ((inputLen-offset)>0){if ((inputLen - offset)>maxDecryptBlock){//第三个参数,要处理的长度cache = cipher.doFinal(decodeBase64,offset,maxDecryptBlock);}else {cache = cipher.doFinal(decodeBase64,offset,inputLen-offset);}baos.write(cache,0,cache.length);i++;offset = i*maxDecryptBlock;}//加密或者解密的结果byte[] bytes = baos.toByteArray();baos.close();return bytes;}
}
4.GUI图形界面及相关控制逻辑
import cn.encrypt.util.Crypto;
import cn.encrypt.util.Rsa;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.PrivateKey;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/*** 加解密工具(GUI)** 完整验签流程应为:* 1.平台生成AES秘钥,此秘钥告知客户端双方都使用此秘钥加密data节点中的JSON字符串数据;* 2.平台与客户端各自生成一对RSA公私钥;互相交换公钥。该公钥用于对方解密sign中的签名信息【sign产生规则(RSA私钥加密):RSA(MD5(业务报文JSON字符串))】;* 2.1.AES解密data节点中的原文JSON字符串数据;* 2.2.将2.1拿到的原文字符串信息进行md5得到签名信息1;* 2.3.通过对方RSA公钥解密sign中数据得到签名信息2;* 2.4.判断两个签名信息是否相等,若相等代表数据未被篡改;*/
public class Main {/*** 主函数* */public static void main(String[] args) {int gap = 10;// AES默认值String AES_MRZ = "KCxblY+b4iqhU4ELDl4xXQ==";// 用户私钥默认值(用于加密签名sign,签名加密规则:RSA(md5(字符串JSON入参))),该sign用于服务器检查客户端上传参数中途是否被篡改。String YHSY_MRZ = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALNv7UQzEucTr/1MSif1kGeSsfTfY01XOkmr7ZO5vP95n/KvTV89o0K1xfk1hGMAp+xxflyHQThGz2LzUTQlXQXQ3fHUVDD5rYirtF03dX5s1MOrhkaCru5/IVUT83k0V3706Yo00PjrQTWx54XLyPVWwok0po7/e1VWTGT5DJHJAgMBAAECgYAI6Xs4Uu0SawjnpL1eJLUqX7/U8K9m7PkpJY/kMWpwqeLG0+wc2dvc+Vg+22ia3jJ47N4gzFrx55pvSLR0yZJIHQ/PqaJ0qR1BgTBaZBAR/S2nmoLo2LxTOh1sG1V0H2J7bPv3FAP4+4CQ5MtbeJFW2IDAQcfTv01TugftEhw8XQJBAP54vzNQPNKOmT5bVxVxIfetm/DHtLduJ5yDX3Lh43XM3rXmhPf886nuQ4g9Yzm1g9Of8qB7dgC4xrXg8NOmzKMCQQC0g9BImwOF5gYfGpw9WbC/vU/TttV1l3M/XvHfjMpzisxUxEEXJtZX7nsjvwjbyMYSTn4n8Rel4bMXXPlztQKjAkBw4AJ/smGoTBRxcnaoTixw/pMjNJJWowfzBtr5zHTmtd879GqazZsPj15pOkGfQYKeBl7LDLiFDXEnEAYC/APdAkARO0P2qlV7wqly7qdbc+RbaUblft6BiyOFORr9rALnZKh8rv9Hpn1vh2RZ1TKTSGcf+D4yseEABLuDz2xAj1bhAkAsnoLWt9O+PZtPOSmmxLD+/6aS786mjG0SuSPUwt07VX43Rv2xUHuKvcJ9KGd2l5iitmG+KFvV8ayLYrA1hWil";JFrame f = new JFrame("企业加解密工具(内部版)V1.0");f.setSize(410, 400);f.setLocation(200, 200);f.setLayout(null);JPanel pInput = new JPanel();pInput.setBounds(gap, gap, 375, 120);pInput.setLayout(new GridLayout(4,3,gap,gap));JLabel aesKey = new JLabel("AES:");JTextField aesKeyText = new JTextField(AES_MRZ); // 在构造函数中传入“字符串参数”为其设置默认值JLabel yhsy = new JLabel("用户私钥:");JTextField yhsyText = new JTextField(YHSY_MRZ); // 在构造函数中传入“字符串参数”为其设置默认值JLabel param = new JLabel("入参明文:");JTextField paramText = new JTextField();JLabel rsp = new JLabel("响应密文:");JTextField rspText = new JTextField();JButton b = new JButton("加密");JButton c = new JButton("解密");// AESpInput.add(aesKey);pInput.add(aesKeyText);// 用户私钥pInput.add(yhsy);pInput.add(yhsyText);// 请求入参pInput.add(param);pInput.add(paramText);// 响应入参pInput.add(rsp);pInput.add(rspText);// 文本域JTextArea ta = new JTextArea();c.setBounds(200, 120 + 30, 80, 30); // 设置解密按钮坐标b.setBounds(70, 120 + 30, 80, 30); // 设置加密按钮坐标ta.setBounds(gap, 150 + 60, 375, 120); // 设置文本域坐标// 创建一个滚动面板,并将文本域添加到滚动面板中JScrollPane scrollPane = new JScrollPane(ta);scrollPane.setBounds(gap, 150 + 60, 375, 120);f.add(pInput); // 抬头及输入框添加到Framef.add(b); // 按钮添加到Framef.add(c); // 按钮添加到Framef.add(scrollPane);// 滚动面板添加到Framef.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setVisible(true);// 加密按钮监听b.addActionListener(new ActionListener(){boolean checkedpass = true;public void actionPerformed(ActionEvent e){checkedpass = true;// 非空校验checkEmpty(aesKeyText,"AES");checkEmpty(yhsyText,"用户私钥");checkEmpty(paramText,"入参明文");String aes = aesKeyText.getText();String yhsy = yhsyText.getText();String params = paramText.getText();if(checkedpass){// data 加密String data = "";String sign = "";// JSON格式校验if(!JSONUtil.isJson(params)){ta.setText("");ta.append("JSON格式错误!");return;}try {data = Crypto.encryptSymmetrically(aes, null, params, Crypto.Algorithm.Encryption.AES_ECB_PKCS5);} catch (Exception e1) {ta.setText("");ta.append("加密失败!");return;}// sign 加密String md5Txet = SecureUtil.md5(params);// 用户私钥加密Rsa rsa = new Rsa();PrivateKey yhsyKey = null;try {yhsyKey = rsa.getPrivateKey(yhsy);sign = rsa.encrypt(md5Txet, yhsyKey);} catch (Exception e1) {ta.setText("");ta.append("加密失败!");return;}Map<String, String> result = new HashMap<>();result.put("data",data);result.put("sign",sign);result.put("requestTime", LocalDateTimeUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss"));ta.setText("");ta.append(JSONUtil.toJsonStr(result));}}// 检验是否为空private void checkEmpty(JTextField tf, String msg){if(!checkedpass)return;String value = tf.getText();if(value.length()==0){JOptionPane.showMessageDialog(f, msg + " 不能为空");tf.grabFocus();checkedpass = false;}}});// 解密按钮监听c.addActionListener(new ActionListener(){boolean checkedpass = true;public void actionPerformed(ActionEvent e){checkedpass = true;// 非空校验checkEmpty(aesKeyText,"AES");checkEmpty(rspText,"响应密文");String aes = aesKeyText.getText();String params = rspText.getText();if(checkedpass){// JSON格式校验if(!JSONUtil.isJson(params)){ta.setText("");ta.append("JSON格式错误!");return;}// 响应数据String rsp = null;JSONObject obj = JSONUtil.toBean(params, JSONObject.class);if("200".equals(obj.getStr("code"))){String data = obj.getStr("data");if(StrUtil.isBlank(data)){ta.setText("");ta.append("数据格式不完整"); // 响应数据缺少data节点return;}/*** 说明:* 此处只对data节点进行AES解密。不模拟使用“平台公钥”对服务器响应的sign进行验签。因为不模拟服务器端的签名,所以代码中未声明“平台公钥”*/try {rsp = Crypto.decryptSymmetrically(aes, null, data, Crypto.Algorithm.Encryption.AES_ECB_PKCS5);ta.setText("");ta.append(rsp); // 解密成功直接返回return;} catch (Exception e1) {ta.setText("");ta.append("解密失败!");return;}}ta.setText("");ta.append(params); // 非200状态码来解密时直接返回原送参数据}}//检验是否为空private void checkEmpty(JTextField tf, String msg){if(!checkedpass)return;String value = tf.getText();if(value.length()==0){JOptionPane.showMessageDialog(f, msg + " 不能为空");tf.grabFocus();checkedpass = false;}}});}
}
项目打包
包含将Maven中依赖用到的jar一并打入到当前程序的jar中;不会的可以看下面的文章;
传送门文章浏览阅读318次。前段时间需要给接口对接方提供一个Jar包,其内容包含接口调用方参数加签,服务提供方响应验签,以及为调用方组装服务提供方需要的入参格式。打工具类Jar实现的目标:1.工具类项目使用Maven管理方便在项目中引入其它需要的依赖;2.工具类项目打好Jar后,此Jar可直接在其它地方导入使用(类似于JDBC驱动Jar);3.打好的工具类Jar中,包含工具类项目使用到的Maven依赖对应的源码包;4.使用IDEA自带的打包方式,不使用Maven打包插件进行打包;_idea打引用jar包 选择携带依赖https://blog.csdn.net/weixin_45876411/article/details/132853766
制作exe执行程序
这篇文章很nice,傻瓜式教程这里就不再重复赘述;传送门文章浏览阅读8.9k次,点赞35次,收藏186次。目录1.GUI插件1.1 下载GUI绘制插件1.GUI插件使用IDEA的朋友们,可能比较头疼了,为什么这里要去下载eclipse的插件,IDEA里面没有吗?其实是有的,但是都是要付费使用的,不得已,我们只有使用eclipse来帮助我们绘制GUI的操作了,GUI界面生成之后,后面的逻辑代码编写,我们还是会在IDEA里面操作。1.1 下载GUI绘制插件下载地址:windowbuilder下载点击link点击下载,从外网下载,速度可能比较慢,建议使用迅雷下载。1.2 ._java开发windows桌面程序https://blog.csdn.net/Jeffhan_java/article/details/123403997
测试
客户端参数加密测试
模拟客户端将明文参数加密成平台接口需要的参数格式;
入参:
{"id":1001}
响应:
{"requestTime":"2024-04-18 16:48:43","data":"bHVEPUh9PFVIJ6lmuhDhrA==","sign":"gPOMELGlFZuj/P7QvdvZf61cSMg4iQ1dUR9/J1BzsZtsIO5dbb2fmwA3UsyeIu7DkDwFxfpfzSKMRgdLFRKDX9IFyoWhBGbmnGWpJn6wysjVErBNiD7rYi5ioK3oSDSJFuPMnmJTKPoodumz3KO4Jy8is2t4icFMN+7LXTI3YCI="}
平台响应解密测试
模拟客户端收到平台处理完后的数据进行解密;
入参
{"data":"U32bMclk9/SQeE46F4sIv9Ns4BqyQZvR71bOADYZpPdOcd3+rJdEkqzA+jgoVUzS67H1tWslzAX6DOXNDTAG1bbDC45eNXqsqESy1rSZoM4=","requestTime":"2024-04-18 17:12:16","code":"200","message":"","responseTime":"2024-04-18 17:12:20","sign":"此处不模拟平台使用平台私钥加密sign签名"}
响应
{"id":1001,"name":"小明","address":"四川省成都市","age":18}
另附项目源码及exe4j安装程序包 ,需要可自行下载;
这篇关于Java GUI + exe4j制作加解密桌面程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!