java、php分别实现兼容的3DES对称加密和解密

最近在对接别人的接口时,对方要求敏感信息传输必须进行3DES加密,并且很贴心提供了一个java Demo。可是我主力后端语言是PHP——世界上最好的语言,java处于勉强看懂的水平,要实现需求,只能踩bug过河了。万幸的是,费了大半天时间,终于解决了。国际惯例,先祭上java实现:

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

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

/**
 * 1) 提供了 TripleDES、AES、SHA1、MD5、BASE64等加解密、编解码工具;
 * 2) 可以在静态导入(import static)这个类,这样用起来更方便;
 */
public final class Crypto {

	public static String code = "UTF-8";

	public static final class TripleDES {
		public static final String encrypt(String data, String secretKey) {
			try {
				// 3DES加密
				byte[] encrpyted = tripleDES(Cipher.ENCRYPT_MODE, data.getBytes(code), secretKey.getBytes());
				byte[] encoded = Base64.encodeBase64(encrpyted); // Base64编码
				return new String(encoded);
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
		}

		public static final String decrypt(String data, String secretKey) {
			try {
				byte[] decoded = Base64.decodeBase64(data); // Base64解码
				byte[] decrypted = tripleDES(Cipher.DECRYPT_MODE, decoded, secretKey.getBytes());// 3DES解密
				return new String(decrypted, code);
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
		}

		private static byte[] tripleDES(int opmode, byte[] data, byte[] secretKey) {
			return cipher("DESede", "DESede/CBC/PKCS5Padding", opmode, data, "01234567".getBytes(), secretKey);
		}
	}

	public static final String SHA256(String data) {
		try {
			return DigestUtils.sha256Hex(data.getBytes(code));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static final String SHA1(String data) {
		try {
			return DigestUtils.sha1Hex(data.getBytes(code));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static final String MD5(String data) {
		try {
			return DigestUtils.md5Hex(data.getBytes(code));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static final String MD5num(String data) {
		try {
			return byteArrayToString(DigestUtils.md5(data.getBytes(code)));
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static final class BASE64 {
		public static final String encode(String data) {
			try {
				return Base64.encodeBase64String(data.getBytes(code));
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
		}

		public static final String decode(String data) {
			try {
				return new String(Base64.decodeBase64(data), code);
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
		}
	}

	private static String byteArrayToString(byte[] b) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			resultSb.append(byteToNumString(b[i]));
		}
		return resultSb.toString();
	}
	
	private static String byteToNumString(byte b) {
		int _b = b;
		if (_b < 0) {
			_b = 256 + _b;
		}
		return String.valueOf(_b);
	}
	
	/**
	 * 通用的对称加密算法
	 * 
	 * @param algorithm
	 *            , 算法名称
	 * @param transformation
	 *            , 算法名称/工作模式/填充模式
	 * @param opmode
	 *            :Cipher.ENCRYPT_MODE和Cipher.DECRYPT_MODE
	 * @param data
	 *            , 明文或密文数据
	 * @param iv
	 *            , 初始化向量
	 * @param secretKey
	 *            ,密钥
	 * @return 加密或解密的结果
	 */
	private static final byte[] cipher(String algorithm, String transformation, int opmode, byte[] data, byte[] iv,
			byte[] secretKey) {
		try {
			// 转换密钥
			Key key = SecretKeyFactory.getInstance(algorithm).generateSecret(new DESedeKeySpec(secretKey));
			// 转换初始化向量
			IvParameterSpec spec = new IvParameterSpec(iv);

			// 加密解密器
			Cipher cipher = Cipher.getInstance(transformation);
			cipher.init(opmode, key, spec);

			// 加密解密操作
			return cipher.doFinal(data);
		} catch (InvalidKeyException | InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException
				| IllegalBlockSizeException | BadPaddingException | InvalidAlgorithmParameterException e) {
			throw new RuntimeException(e);
		}
	}
	
}

php实现:

<?php
    class TripleDES{
        public function encrypt3DES($input, $key) {
            // $str = self::pkcs5_pad($input, 8);
            $str = $input;
            if (strlen($str) % 8) {
                $str = str_pad($str,strlen($str) + 8 - strlen($str) % 8, "\0");
            }
            // $sign = openssl_encrypt ($str, 'DES-EDE3-CBC' ,$key,OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,'01234567');
            $sign = openssl_encrypt ($str, 'DES-EDE3-CBC' ,$key,1,'01234567');
            return base64_encode($sign);
            // return $sign;
        }

        public function pkcs5_pad ($text, $blocksize) {
            $pad = $blocksize - (strlen($text) % $blocksize);
            return $text . str_repeat(chr($pad), $pad);
        }

        public function decrypt3DES($data,$method,$key,$options,$iv){
            $output = openssl_decrypt($data, $method,$key,$options,$iv);
            return $output;
        }
    }

?>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值