3DES ECB ZeroPadding

  • 前言
    • 解决
    • 相关类

前言

因金融机构支付相关的接口需要对敏感数据加密,采用3DES加密。刚开始以为这个加密网上找一大堆,没想到一无所获。

解决

由于不熟悉这个加密,对数据的位数不足填充不是特别了解,功力不够。最后终于在github找到了。
github地址:https://github.com/quanqiang-li/knowledge

相关类

加密类 CipherUtil.

// import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Base64;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;/*** 公钥加密,私钥解密* <p>* 证书算法: x509Certificate.getSigAlgName() 用来加签/验签 <br>* keytool -genkeypair -sigalg SHA1withRSA <br>* 密钥算法:key.getAlgorithm() 用来加密/解密 创建密钥对的时候指定的 <br>* keytool -genkeypair -keyalg RSA<br>* * @author aisino 参考顺序*         MessageDigestUtil--》KeyToolUtil--》SignatureUtil--》CipherUtil*/
public class CipherUtil {public static final String CHARSET_UTF8 = "UTF-8";public static final String Algorithm_AES = "AES";public static final String Algorithm_DES = "DES";public static final String Algorithm_DESede = "DESede";// 也叫3DES/模式/填充,默认等同于DESede/ECB/PKCS5Paddingpublic static final String Algorithm_RSA = "RSA";public static final String Algorithm_PBEWithMD5AndDES = "PBEWithMD5AndDES";public static void main(String[] args) {//      String msg = "你好hello12a c";
//      Certificate certificate = KeyToolUtil.getCert("carl.crt");
//      String encryptMsg = encryptMsg(msg, certificate);
//      System.out.println(certificate.getPublicKey().getAlgorithm() + "加密串:" + encryptMsg);
//      PrivateKey privateKey = KeyToolUtil.getPrivateKeyFromKeyStore("JKS", "carl.keystore", "qq2476056494", "carl",
//              "qq2476056494");
//      String decryptMsg = decryptMsg(encryptMsg, privateKey);
//      System.out.println(privateKey.getAlgorithm() + "解密后:" + decryptMsg);
//      System.out.println("==============以下是采用密钥串来加解密的===================");
//      // 3des的密钥串只能是24个字节的长度,采用utf编码则24个字母数字,或者8个中文
//      String key = "abcdefghijklmnopqrstuvwx";
//      String encryptMsg2 = encryptMsg(key, Algorithm_DESede, msg);
//      System.out.println("\n" + Algorithm_DESede + "加密串:" + encryptMsg2);
//      String decryptMsg2 = decryptMsg(key, Algorithm_DESede, encryptMsg2);
//      System.out.println("\n" + Algorithm_DESede + "解密后:" + decryptMsg2);System.out.println("==============以下是3des/ecb/zeroPadding加解密的===================");String deskey = "111111111111111111111111";String encryptWithDESCEBZeroPading = encryptWithDESCEBZeroPading(deskey, "511113197310071016");System.out.println("\n加密串" + encryptWithDESCEBZeroPading);String decryptWithDESCEBZeroPading = decryptWithDESCEBZeroPading(deskey, encryptWithDESCEBZeroPading);System.out.println("\n解密串" + decryptWithDESCEBZeroPading);}/*** 加密数据,证书里公钥的算法* * @param msg*            数据* @param certificate*            证书(公钥)* @return base64编码处理的字符串*/public static String encryptMsg(String msg, Certificate certificate) {try {// 使用证书公钥的算法,生成密钥对的时候指定的算法Cipher instance = Cipher.getInstance(certificate.getPublicKey().getAlgorithm());// ENCRYPT_MODE 加密模式instance.init(Cipher.ENCRYPT_MODE, certificate);instance.update(msg.getBytes(CHARSET_UTF8));byte[] doFinal = instance.doFinal();return Base64.getEncoder().encodeToString(doFinal);} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}/*** 解密数据,私钥的算法* * @param encryptMsg*            加密后字符串,且base64编码处理过* @param privateKey*            私钥* @return 解密后的数据*/public static String decryptMsg(String encryptMsg, PrivateKey privateKey) {try {// 使用私钥的算法,生成密钥对的时候指定的算法Cipher instance = Cipher.getInstance(privateKey.getAlgorithm());// DECRYPT_MODE 解密模式instance.init(Cipher.DECRYPT_MODE, privateKey);instance.update(Base64.getDecoder().decode(encryptMsg));byte[] doFinal = instance.doFinal();return new String(doFinal, CHARSET_UTF8);} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}/*** 没有证书的情况下,采用指定密钥串加密* * @param key*            密钥* @param Algorithm*            加密算法* @param msg*            消息* @return Base64编码后的字符串*/public static String encryptMsg(String key, String Algorithm, String msg) {try {// 生成密钥byte[] bytes = key.getBytes(CHARSET_UTF8);System.out.println("密钥字节长度:" + bytes.length);SecretKey deskey = new SecretKeySpec(bytes, Algorithm);// 加密工具Cipher c1 = Cipher.getInstance(Algorithm);// 加密c1.init(Cipher.ENCRYPT_MODE, deskey);byte[] msgBytes = msg.getBytes(CHARSET_UTF8);System.out.println("原数据字节如下:");for (int i = 0; i < msgBytes.length; i++) {System.out.print(msgBytes[i] + "\t");}// FIXME 此处不能使用updatebyte[] doFinal = c1.doFinal(msgBytes);System.out.println("\n加密后的字节如下:");for (int i = 0; i < doFinal.length; i++) {System.out.print(doFinal[i] + "\t");}return Base64.getEncoder().encodeToString(doFinal);} catch (Exception e) {e.printStackTrace();}return null;}/*** 3des ecb 0填充,利用NoPading,自行补0* * @param key*            密钥串,必须为24长度字符串* @param msg*            消息* @return Base64编码后的字符串*/public static String encryptWithDESCEBZeroPading(String key, String msg) {try {// 生成密钥byte[] bytes = key.getBytes(CHARSET_UTF8);System.out.println("密钥字节长度:" + bytes.length);SecretKey deskey = new SecretKeySpec(bytes, "DESede");// 加密工具Cipher c1 = Cipher.getInstance("DESede/ECB/NoPadding");// 加密c1.init(Cipher.ENCRYPT_MODE, deskey);byte[] msgBytes = msg.getBytes(CHARSET_UTF8);System.out.println("原数据字节如下:");for (int i = 0; i < msgBytes.length; i++) {System.out.print(msgBytes[i] + "\t");}// FIXME 自行补位,达到8字节的倍数int remainder = msgBytes.length % 8;if (0 != remainder) {int oldLength = msgBytes.length;// 1.扩展自身长度msgBytes = Arrays.copyOf(msgBytes, msgBytes.length + 8 - remainder);// 2.填充扩展内容为0Arrays.fill(msgBytes, oldLength, msgBytes.length, (byte) 0);}// FIXME 此处不能使用update,自行补位,byte[] doFinal = c1.doFinal(msgBytes);System.out.println("\n加密后的字节如下:");for (int i = 0; i < doFinal.length; i++) {System.out.print(doFinal[i] + "\t");}return Base64.getEncoder().encodeToString(doFinal);} catch (Exception e) {e.printStackTrace();}return null;}/*** 没有证书的情况下,使用密钥串解密* * @param key*            密钥串* @param Algorithm*            算法* @param encryptMsg*            已加密的字节经base64编码后的字符串* @return 原始数据,utf-8编码*/public static String decryptMsg(String key, String Algorithm, String encryptMsg) {try {// 生成密钥byte[] bytes = key.getBytes(CHARSET_UTF8);System.out.println("密钥字节长度:" + bytes.length);SecretKey deskey = new SecretKeySpec(bytes, Algorithm);// 初始工具Cipher instance = Cipher.getInstance(Algorithm);// DECRYPT_MODE 解密模式instance.init(Cipher.DECRYPT_MODE, deskey);byte[] encryptMsgBytes = Base64.getDecoder().decode(encryptMsg);System.out.println("待解密的字节如下:");for (int i = 0; i < encryptMsgBytes.length; i++) {System.out.print(encryptMsgBytes[i] + "\t");}// FIXME 此处不能使用updatebyte[] doFinal = instance.doFinal(encryptMsgBytes);System.out.println("\n解密后的字节为如下:");for (int i = 0; i < doFinal.length; i++) {System.out.print(doFinal[i] + "\t");}return new String(doFinal, CHARSET_UTF8);} catch (Exception e) {e.printStackTrace();}return null;}/*** 3des ecb 0填充,解密;利用NoPading,自行去除填充的0* * @param key*            密钥字符串,必须是24长度* @param encryptMsg*            base64的密文* @return*/public static String decryptWithDESCEBZeroPading(String key, String encryptMsg) {try {// 生成密钥byte[] bytes = key.getBytes(CHARSET_UTF8);System.out.println("密钥字节长度:" + bytes.length);SecretKey deskey = new SecretKeySpec(bytes, "DESede");// 初始工具Cipher instance = Cipher.getInstance("DESede/ECB/NoPadding");// DECRYPT_MODE 解密模式instance.init(Cipher.DECRYPT_MODE, deskey);byte[] encryptMsgBytes = Base64.getDecoder().decode(encryptMsg);System.out.println("待解密的字节如下:");for (int i = 0; i < encryptMsgBytes.length; i++) {System.out.print(encryptMsgBytes[i] + "\t");}// FIXME 此处不能使用updatebyte[] doFinal = instance.doFinal(encryptMsgBytes);// 去除填充的0,倒数第一个不为0的位置,copy到另一个数组int zeroIndex = doFinal.length;for (int i = doFinal.length - 1; i > 0; i--) {if (doFinal[i] == (byte) 0) {zeroIndex = i;} else {break;}}doFinal = Arrays.copyOf(doFinal, zeroIndex);System.out.println("\n解密后的字节为如下:");for (int i = 0; i < doFinal.length; i++) {System.out.print(doFinal[i] + "\t");}return new String(doFinal, CHARSET_UTF8);} catch (Exception e) {e.printStackTrace();}return null;}}

依赖的工具类 KeyToolUtil


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;import sun.security.tools.keytool.Main;/*** 密钥和证书管理工具* * @author aisino* 参考顺序* MessageDigestUtil--》KeyToolUtil--》SignatureUtil--》CipherUtil*/
public class KeyToolUtil {public static void main(String[] args) throws Exception {//命令:keytool -list -keystore test.keystore//这里省略开头的keytool,这里Main本身就是keytool工具,使用空格拆分的命令//printAllCommand();//printCommandHelp("export");//生成密钥对,会提示输入密码,机构;域名liquanqiang.aisino.com来倒着填,按地址倒着填,keyalg 加解密用,sigalg 加签验签用,这两个算法要属于一个体系内//execCommand("-genkeypair -alias carl1 -keyalg RSA -sigalg SHA1withRSA -keysize 1024 -validity 365 -keystore carl1.keystore");//列出密钥库中的条目//execCommand("-list -keystore carl1.keystore");//从密钥库导出公钥到证书//execCommand("-export -alias carl1 -file carl1.crt -keystore carl1.keystore");//打印证书内容execCommand("-printcert -file carl1.crt");
//      System.out.println(getStrFromKey(getPublicKeyFromCert(getCertFromKeyStore("JKS", "carl.keystore", "qq2476056494", "carl"))));
//      System.out.println(getStrFromKey(getPublicKeyFromCert(getCert("carl.crt"))));
//      System.out.println(getStrFromKey(getPrivateKeyFromKeyStore("JKS", "carl.keystore", "qq2476056494", "carl","qq2476056494")));}/*** 打印keytool的所有命令*/public static void printAllCommand(){try {Main.main(("-help").split("\\s"));} catch (Exception e) {e.printStackTrace();}}/*** 打印keytool的指定命令帮助信息* @param commandName*/public static void printCommandHelp(String commandName){try {Main.main(("-"+commandName + " -help").split("\\s"));} catch (Exception e) {e.printStackTrace();}}/*** 通用的命令执行* @param command*/public static void execCommand(String command){try {Main.main((command).split("\\s"));} catch (Exception e) {e.printStackTrace();}}/*** 获取密钥库中的证书* @param keyStoreType 密钥库的条目类型,-list可以查看* @param keyStorePath 密钥库的文件路径* @param keyStorePass 密钥库密码* @param alias 条目别名* @return*/public static Certificate getCertFromKeyStore(String keyStoreType,String keyStorePath,String keyStorePass,String alias){try {//因为生成证书的类型为JKS 也有其他的格式  -list可以查看密钥库的条目类型KeyStore keyStore = KeyStore.getInstance(keyStoreType);  //读取keystore文件转换为keystore密钥库对象  FileInputStream fis = new FileInputStream(keyStorePath);  //该密钥库的密码keyStore.load(fis, keyStorePass.toCharArray());  fis.close();  // 从keystore中获取证书然后进一步获取公钥Certificate certificate = keyStore.getCertificate(alias);return certificate;} catch (KeyStoreException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (CertificateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}/*** 直接读取证书* @param certPath 证书目录* @return*/public static Certificate getCert(String certPath){try {//证书类型只支持X.509CertificateFactory factory = CertificateFactory.getInstance("X.509");// 取得证书文件流FileInputStream inputStream = new FileInputStream(certPath);// 生成证书Certificate certificate = factory.generateCertificate(inputStream);inputStream.close();return certificate;} catch (CertificateException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}/*** 从证书读取公钥,java只支持X509Certificate* @param certificate* @return*/public static PublicKey getPublicKeyFromCert(Certificate certificate){//读取公钥对象  X509Certificate x509Certificate = (X509Certificate) certificate;PublicKey publicKey = certificate.getPublicKey();System.out.println("证书算法:" + x509Certificate.getSigAlgName());System.out.println("公钥算法:" + publicKey.getAlgorithm());return publicKey;}/*** 获取密钥库中的私钥内容* @param keyStoreType 密钥库的条目类型,keytool -list可以查看* @param keyStorePath 密钥库的文件路径* @param keyStorePass 密钥库密码* @param alias 条目别名* @param aliasPass 条目密码* @return*/public static PrivateKey getPrivateKeyFromKeyStore(String keyStoreType,String keyStorePath,String keyStorePass,String alias,String aliasPass){try {//因为生成证书的类型为JKS 也有其他的格式  -list可以查看密钥库的条目类型KeyStore keyStore = KeyStore.getInstance(keyStoreType);  //读取keystore文件转换为keystore密钥库对象  FileInputStream fis = new FileInputStream(keyStorePath);  //该密钥库的密码keyStore.load(fis, keyStorePass.toCharArray());  fis.close();  PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, aliasPass.toCharArray());return privateKey;} catch (KeyStoreException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (CertificateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (UnrecoverableKeyException e) {e.printStackTrace();}return null;}/*** 从key获取密钥串* @param key* @return base64编码处理后的字符串*/public static String getStrFromKey(Key key){//64位编码处理return Base64.getEncoder().encodeToString(key.getEncoded());}/*** 从字符串还原回key* @param encodedKey  base64编码处理后的字符串* @param algorithm 指定算法* @return 还原的key*/public static SecretKey getKeyFromStr(String encodedKey,String algorithm){// decode the base64 encoded stringbyte[] decodedKey = Base64.getDecoder().decode(encodedKey);// rebuild key using SecretKeySpecSecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, algorithm); return originalKey;}
}

至此,终于解决了。心情瞬间舒畅!

JAVA 3DES加密 ECB模式 ZeroPadding填充相关推荐

  1. Python实现AES中ECB模式pkcs5padding填充加密/解密(需要加密文档中可以有中文)

    Python实现AES中ECB模式pkcs5padding填充加密/解密(需要加密文档中可以有中文) 一.本文主要解决的问题 二.完整版代码 结果: 三.遇到的问题 1.填充格式错误 2.传入类型错误 ...

  2. python 3des加密_DES/3DES之ECB模式和CBC模式加解密 及 Python 实现

    概念说明 DES:Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法. 3DES:Triple DES,是三重数据加密算法(TDEA,Triple Data ...

  3. java 3des加密_Java使用3DES加密解密的流程 - 3des加密解密详细解释

    Java使用3DES加密解密的流程 ①传入共同约定的密钥(keyBytes)以及算法(Algorithm),来构建SecretKey密钥对象 SecretKey deskey = new Secret ...

  4. C++调用openssl实现DES加密解密cbc模式 zeropadding填充方式 pkcs5padding填充方式 pkcs7padding填充方式...

    ============================================== des   cbc  加密 zeropadding填充方式 ======================= ...

  5. 前端JavaScript AES解密 AES加密 ECB模式

    项目里使用过md5.base64,使用AES的安全系数会高一些. 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法,微信小程序加密传输就是用这个加 ...

  6. node和java 3des加密解密

    node npm i crypto import * as crypto from 'crypto' /*** rsa 256签名* @param data*/ export function cre ...

  7. 微信小程序 AES加密ECB模式

    微信小程序 AES加密网上大部分是CBC模式,但是java后台用的是ECB模式 ECB模式 js文件下载 下载链接 (有好多写着ECB模式,但是下载了还是CBC的,可恨-) 下面展示一下两种模式解密结 ...

  8. Android AES文件加密 ECB模式

    项目过程中遇到一个新需求,对文件进行AES加密解密,要求用ECB模式,这里记录一下 网上找了很多资料,对字符串进行加密很多,可是我需要的是对文件进行加密,一开始的思路是把文件内容读出来,然后对这些内容 ...

  9. Java 3DES加密解密(Commons.Codec Base64)

    依赖包 import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.binary.Base6 ...

最新文章

  1. 继承和多态 2.0 -- 继承的六个默认成员函数
  2. 【cocos2d-x从c++到js】21:使用CocosCode调试JSB
  3. C++ 标准库中的异常
  4. C语言:关键字volatile详解!
  5. PyTorch深度学习实践02
  6. Eureka服务注册中心---SpringCloud
  7. 【AI视野·今日CV 计算机视觉论文速览 第227期】Fri, 25 Jun 2021
  8. XSS-Game level 7
  9. 计算尖峰电流的目的_干货 | 谈谈RCD的计算方法
  10. 首信易支付 php,ZenCart首信易支付模块递交失败解决
  11. java 数字游戏的方法_java实现猜数字游戏
  12. CDM以及ACDM相关的时间、时刻专有词汇说明
  13. 超级电容模组电压不均衡特性分析
  14. Ubuntu如何发音
  15. 前端一键换肤换肤简单探索
  16. 使用Altium Designer报错的处理记录 1 :Class Document Source Message Time Date No.
  17. 人物 | 张忠谋:老将二度离场
  18. js 根据时间戳格式化为24小时的日期形式
  19. 全新Pervasive SQL Summit V10数据库
  20. 20款开发运维必备的顶级工具,速收

热门文章

  1. 电脑上不了网?常见问题的解决办法
  2. 最新伦敦金行情分析技巧:由小变大 循序渐进
  3. 战略的意义与战略的产生——剖析盛大的网游新战略
  4. 信息系统项目管理师教程第三版 考试重点
  5. 3000xp7.32突然显示主数据库不存在的解决一例
  6. 动手学深度学习第二版 Ubuntu import os os.makedirs(os.path.join(‘..‘, ‘data‘), exist_ok=True)data_f报错
  7. 最新:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)周志明
  8. vba学习笔记 while wend 的使用
  9. T2080RDB: UBoot boot vxWorks SMP
  10. HDR in OpenGL