加密算法-密码安全

密码安全

摘要加密

摘要是哈希值,我们通过散列算法比如MD5算法就可以得到这个哈希值。摘要只是用于验证数据完整性和唯一性的哈希值,不管原始数据是什么样的,得到的哈希值都是固定长度的。 不管原始数据是什么样的,得到的哈希值都是固定长度的,也就是说摘要并不是原始数据加密后的密文,只是一个验证身份的令牌。所以我们无法通过摘要解密得到原始数据。

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函 数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由 美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套 算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于 需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞 (collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。 MD5存在一个缺陷,只要明文相同,那么生成的MD5码就相同,于是攻击者就可以通过撞库的方式 来破解出明文。加盐就是向明文中加入指定字符,主要用于混淆用户、并且增加MD5撞库破解难度,这样一来即使撞库破解,知道了明文,但明文也是混淆了的,真正需要用到的数据也需要从明文中摘取, 摘取范围、长度、摘取方式都是个谜,如此一来就大大增加了暴力破解的难度,使其几乎不可能破解。

摘要加密算法

  1. MD5算法法(MD2 、MD4、MD5)
  2. SHA算法(SHA1、SHA256、SHA384、 SHA512)
  3. HMAC算法

特点

  1. 任何数据加密,得到的密文长度固定。
  2. 密文是无法解密的(不可逆)。

验签

验签其实就是签名验证,MD5加密算法经常用于签名安全验证。疑问:要是密文也一起改了再传过去呢?

代码示例

import org.apache.commons.codec.digest.DigestUtils;

public class MD5Util {

    /**
     * MD5方法
     *
     * @param text 明文
     * @return 密文
     * @throws Exception
     */
    public static String md5(String text) throws Exception {
        //加密后的字符串
        String encode = DigestUtils.md5Hex(text);
        return encode;
    }

    /**
     * MD5方法
     *
     * @param text 明文
     * @param key  盐
     * @return 密文
     * @throws Exception
     */
    public static String md5(String text, String key) throws Exception {
        //加密后的字符串
        String encode = DigestUtils.md5Hex(text + key);
        return encode;
    }

    /**
     * MD5验证方法
     *
     * @param text 明文
     * @param key  密钥/盐
     * @param md5  密文
     * @return true/false
     * @throws Exception
     */
    public static boolean verify(String text, String key, String md5) throws Exception {
        //根据传入的密钥进行验证
        String md5Text = md5(text, key);
        return md5Text.equalsIgnoreCase(md5);
    }

    public static void main(String[] args) throws Exception {
        String test = "admin";
        String key = "tiger";
        String md5 = "bcf918bd662986b3bcab0f9a32a21e1d";
        String md5Str = md5(test, key);
        System.out.println(md5Str);
        boolean passOrNot = verify(test, key, md5);
        System.out.println(passOrNot);
    }
}

Base64

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印 字符来表示二进制数据的方法。

解决编码问题

代码示例

import java.util.Base64;

public class Base64Util {

    /***
     * 普通解密操作
     * @param encodedText:密文
     * @return
     */
    public static byte[] decode(String encodedText) {
        final Base64.Decoder decoder = Base64.getDecoder();
        return decoder.decode(encodedText);
    }

    /***
     * 普通加密操作
     * @param data
     * @return
     */
    public static String encode(byte[] data) {
        final Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(data);
    }

    /***
     * 解密操作
     * @param encodedText
     * @return
     */
    public static byte[] decodeURL(String encodedText) {
        final Base64.Decoder decoder = Base64.getUrlDecoder();
        return decoder.decode(encodedText);
    }

    /***
     * 加密操作
     * @param data
     * @return
     */
    public static String encodeURL(byte[] data) {
        final Base64.Encoder encoder = Base64.getUrlEncoder();
        return encoder.encodeToString(data);
    }

    public static void main(String[] args) throws Exception {
        String str = "今天的饭真好吃啊!明天还来!";

        // 加密
        String encode = encode(str.getBytes("UTF-8"));
        // 解密
        byte[] decode = decode(encode);
        // 字节数组 -》字符串
        String text = new String(decode, "UTF-8");
        System.out.println("密文:" + encode);
        System.out.println("明文:" + text);

        // URL
        // 加密
        String encodeURL = encodeURL(str.getBytes("UTF-8"));
        // 解密
        byte[] decodeURL = decodeURL(encodeURL);
        // 字节数组 -》字符串
        String textURL = new String(decodeURL, "UTF-8");
        System.out.println("密文:" + encodeURL);
        System.out.println("明文:" + textURL);
    }
}

对称加密AES

典型的对称加密算法有AES、DES、3DES,但AES加密算法的安全性要高于DES和3DES,所以AES 已经成为了主要的对称加密算法。

AES加密算法就是众多对称加密算法中的一种,它的英文全称是Advanced Encryption Standard, 翻译过来是高级加密标准,它是用来替代之前的DES加密算法的。 要理解AES的加密流程,会涉及到AES加密的五个关键词,分别是:分组密码体制、Padding、密 钥、初始向量IV和四种加密模式

代码示例

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class AESUtil {

    /**
     * AES加密/解密
     *
     * @param buffer:密文/明文
     * @param secretKey:秘钥
     * @param mode:加密/解密模式 1 加密  2 解密
     * @return
     */
    public static byte[] encryptAndDecrypt(byte[] buffer, String secretKey, Integer mode) throws Exception {
        // 1、加载加密解密算法处理对象(包含算法、秘钥管理)
        Security.addProvider(new BouncyCastleProvider());

        // 2、根据不同算法创建秘钥   1)秘钥的字节数组   2)加密算法
        SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes("UTF-8"), "AES");

        // 3、设置加密模式(无论是加密还是解析,模式一致)
        //   1)、AES/ECB/KPS7Padding 设置算法
        //   2)、指定算法库对象
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        // 4、初始化加密配置
        cipher.init(mode, secretKeySpec);
        // 5、执行加密/解密
        return cipher.doFinal(buffer);
    }

    /***
     * 加密解密测试
     * 密钥:128(16)、192(24)、256(32)
     */
    public static void main(String[] args) throws Exception {
        // 明文
        String plainText = "SpringCloud Alibaba";
        // 128bit 16位密钥
        String secretKey = "1234567890123456";
        // 将128bit 16位密钥 -》 256bit 32位密钥
        secretKey = MD5Util.md5(secretKey);
        System.out.println("明文:" + plainText);
        System.out.println("密钥:" + secretKey);

        // 加密
        byte[] bytes = encryptAndDecrypt(plainText.getBytes("UTF-8"), secretKey, 1);
        // 编码
        String encodeStr = Base64Util.encode(bytes);
        System.out.println("密文:" + encodeStr);

        //解密 ->解码Base64->解密
        byte[] decodeStr = encryptAndDecrypt(Base64Util.decode(encodeStr), secretKey, 2);
        System.out.println("解密后数据:" + new String(decodeStr, "UTF-8"));
    }
}

微信支付-Native

接口文档

https://pay.weixin.qq.com/wiki/doc/api/index.html

流程说明

  1. 商户后台系统根据用户选购的商品生成订单。
  2. 用户确认支付后调用微信支付【统一下单API】生成预支付交易;
  3. 微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。
  4. 商户后台系统根据返回的code_url生成二维码。
  5. 用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。
  6. 微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。
  7. 用户在微信客户端输入密码,确认支付后,微信客户端提交授权。
  8. 微信支付系统根据用户授权完成支付交易。
  9. 微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。
  10. 微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。
  11. 未收到支付通知的情况,商户后台系统调用【查询订单API】。
  12. 商户确认订单已支付后给用户发货。

开发步骤

  1. 过修改官方wxpay-sdk源码,将抽象方法的修饰符从默认修改为public, 然后重新打包到本地或者私服

    import com.github.wxpay.sdk.IWXPayDomain;
    import com.github.wxpay.sdk.WXPayConfig;
    import com.github.wxpay.sdk.WXPayConstants;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    @Component
    public class WeixinPayConfig extends WXPayConfig {
    
        //微信支付信息
        @Value("${payconfig.weixin.appId}")
        private String appId;       //应用ID
        @Value("${payconfig.weixin.mchID}")
        private String mchID;       //商户号
        @Value("${payconfig.weixin.key}")
        private String key;         //秘钥
        @Value("${payconfig.weixin.notifyUrl}")
        private String notifyUrl;   //回调地址
        @Value("${payconfig.weixin.certPath}")
        private String certPath;    //证书路径
        //证书字节数组
        private byte[] certData;
    
        @Override
        public String getAppID() {
            return this.appId;
        }
    
        @Override
        public String getMchID() {
            return this.mchID;
        }
    
        @Override
        public String getKey() {
            return this.key;
        }
    
        /***
         * 获取商户证书内容
         * @return
         */
        @Override
        public InputStream getCertStream() {
            /****
             * 加载证书
             */
            if (certData == null) {
                synchronized (WeixinPayConfig.class) {
                    try {
                        if (certData == null) {
                            File file = new File(certPath);
                            InputStream certStream = new FileInputStream(file);
                            this.certData = new byte[(int) file.length()];
                            certStream.read(this.certData);
                            certStream.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
            return certBis;
        }
    
        /***
         * 获取WXPayDomain, 用于多域名容灾自动切换
         * @return
         */
        @Override
        public IWXPayDomain getWXPayDomain() {
            // 这个方法需要这样实现, 否则无法正常初始化WXPay
            IWXPayDomain iwxPayDomain = new IWXPayDomain() {
                @Override
                public void report(String domain, long elapsedTimeMillis, Exception ex) {
    
                }
    
                @Override
                public DomainInfo getDomain(WXPayConfig config) {
    
                    return new DomainInfo(WXPayConstants.DOMAIN_API, true);
                }
            };
            return iwxPayDomain;
        }
    }
    
  2. 微信支付\证书和秘钥中的证书以及秘钥配置导入到 mall-pay-service 工程中,如果是php开发,采用pem证书,如果是java开发采用p12证书

  3. 创建 WXPay 的实例并交给Spring容器管理

    import com.github.wxpay.sdk.WXPay;
    import com.gupaoedu.vip.mall.pay.config.WeixinPayConfig;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootApplication
    @MapperScan(basePackages = {"com.tiger.mall.pay.mapper"})
    public class MallPayApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MallPayApplication.class, args);
        }
    
        /****
         * 微信支付SDK对象
         * @param weixinPayConfig
         * @return
         * @throws Exception
         */
        @Bean
        public WXPay wxPay(WeixinPayConfig weixinPayConfig) throws Exception {
            return new WXPay(weixinPayConfig);
        }
    }
    

微信退款

你可能感兴趣的:(安全,安全,哈希算法,算法,加密算法)