java之加密安全

博客介绍了加密的分类,包括双向和单向加密,双向又分对称和非对称。因工作需求对服务进行过期授权操作,采用依赖jar包方式,使用AES加密。详细介绍创建jar工程过程,含pom.xml、实现类等,还提及在Linux系统遇到的校验码加密问题及解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。大体上分为双向加密和单向加密,而双向加密又分为对称加密和非对称加密(有些资料将加密直接分为对称加密和非对称加密)。
双向加密大体意思就是明文加密后形成密文,可以通过算法还原成明文。而单向加密只是对信息进行了摘要计算,不能通过算法生成明文,单向加密从严格意思上说不能算是加密的一种,应该算是摘要算法吧。
最近在工作中接到一个需求要对服务进行过期授权的操作,在硬件方面使用加密狗usb(类似U盘的东西),另一种是通过服务端进行过期校验,不论哪种的方式都不会是绝对的安全。
思路:使用一个依赖jar包的方式提供过期时间验证,该包中设置过期时间以及对其加密/解密验证,集成到外部网关服务中对外部请求进行拦截校验。所以jar包要进行防止反编译而暴露验证方式。
在该章文章中先介绍一下我了解到的加密的几种方式,借荐于

https://blog.youkuaiyun.com/u013651026/article/details/79167360

该文章介绍的AES(全称为“Advanced Encryption Standard”,中文名“高级加密标准”,在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。) 想了解其他的加密方式可借鉴该文章。
下面就介绍本人使用AES加密方式的过程以及遇到的问题。

创建jar工程

  • pom.xml
 <dependencies>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>
  • 实现类
    代码结构:
    在这里插入图片描述

  • 常量类

public class ServiceExpiredConstant {

	/*加密后的过期时间*/
    public static final String EXPIRED_TIME_STRING = "6MSktJfBKcKr+QmVQPnRCmcGDOw1DEP53mb2f2xtmX4=";
	/*时间格式*/
    public static final String SIMPLE_DATE_FORMAT_STRING = "yyyy-MM-dd HH:mm:ss";

    public static final String KEY_ALGORITHM_STRING = "AES";

    /*算法/模式/补码方式*/
    public static final String DEFAULT_CIPHER_ALGORITHM_STRING = "AES/ECB/PKCS5Padding";

    /**
     * 签名算法
     */
    public static final String SIGN_ALGORITHMS = "SHA1PRNG";
    /*编码格式*/
    public static final String UTF_8_STRING = "utf-8";
 	
    public static final String PASS_WORD_STRING = "验证码";
}
  • 加密工具类
	public class AESUtil {


    /**
     * AES 加密操作
     *
     * @param content  待加密内容
     * @param password 加密密码
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String password) {
        try {
            Cipher cipher = Cipher.getInstance(ServiceExpiredConstant.DEFAULT_CIPHER_ALGORITHM_STRING);// 创建密码器
            byte[] byteContent = content.getBytes(ServiceExpiredConstant.UTF_8_STRING);
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器
            byte[] result = cipher.doFinal(byteContent);// 加密
            return Base64.encodeBase64String(result);//通过Base64转码返回
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    /**
     * AES 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {

        try {
            //实例化
            Cipher cipher = Cipher.getInstance(ServiceExpiredConstant.DEFAULT_CIPHER_ALGORITHM_STRING);
            //使用密钥初始化,设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
            //执行操作
            byte[] result = cipher.doFinal(Base64.decodeBase64(content));
            return new String(result, ServiceExpiredConstant.UTF_8_STRING);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }


    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String password) {
        //返回生成指定算法密钥生成器的 KeyGenerator 对象
        KeyGenerator kg = null;
        try {
            kg = KeyGenerator.getInstance(ServiceExpiredConstant.KEY_ALGORITHM_STRING);
            /*补充*/
            SecureRandom random = SecureRandom.getInstance(ServiceExpiredConstant.SIGN_ALGORITHMS);
            try {
                random.setSeed(password.getBytes(ServiceExpiredConstant.UTF_8_STRING));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            //AES 要求密钥长度为 128
            
			// kg.init(128, new SecureRandom(password.getBytes()));
            kg.init(128, random);
            //生成一个密钥
            SecretKey secretKey = kg.generateKey();
            return new SecretKeySpec(secretKey.getEncoded(), ServiceExpiredConstant.KEY_ALGORITHM_STRING);// 转换为AES专用密钥
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return null;
    }
  • 配置类
	public class ServiceExpiredConfig {
    public static long getEndTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(ServiceExpiredConstant.SIMPLE_DATE_FORMAT_STRING);
        ParsePosition pos = new ParsePosition(0);

        Date strtodate = formatter.parse(AESUtil.decrypt(ServiceExpiredConstant.EXPIRED_TIME_STRING, ServiceExpiredConstant.PASS_WORD_STRING), pos);
        return strtodate.getTime();
    }

    public static long getNowTime() {
        return System.currentTimeMillis();
    }

    public static String encrypt(String content, String password) {
        return AESUtil.encrypt(content,password);
    }

    public static String decrypt(String content, String password) {
        return AESUtil.decrypt(content,password);
    }

}
  • 暴露外部方法类
public class ServiceExpired {

    public static Boolean timeExpired() {
        if (ServiceExpiredConfig.getNowTime() > ServiceExpiredConfig.getEndTime()) {
            return true;
        }
        return false;
    }

    public static String encrypt(String content, String password) {
        return ServiceExpiredConfig.encrypt(content,password);
    }

    public static String decrypt(String content, String password) {
        return ServiceExpiredConfig.decrypt(content,password);
    }

    public static Long getEntTime(){
        return ServiceExpiredConfig.getEndTime();
    }

}

遇到问题:
在本地Windows系统上完全可以,但是在Linux系统上就会报错,
问题出现在校验码加密的方式上,上述代码已是正确的代码,在Linux上也是ok的。

https://www.cnblogs.com/Darlin356230410/p/8602674.html

javax.crypto.BadPaddingException: Given final block not properly padded
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值