Golang、PHP、Java、C#、ObjectC互通DES加密与解密

在完成一个大项目时候,我们要用到多语言来开发接口,每个模块可能分配到各小组中,各小组成员用到语言往往不一样,在向接口传递参数的时候,就要用到加密与解密。

在网上找了一些,这篇文章中有通用的写法,《PHP、JAVA、C#、Object-C 通用的DES加密》。

我只对PHP和Golang加密与解密进行了修改,其它语言并没有修改!

PHP:

/**
 * @desc DES加密码与解密
*/
class Des {
	//密钥8位
	public $key = '256&#@$M';

	/**
	 * @desc 加密返回大写十六进制字符串
	 * @param string $str
	 * @return string
	 */
	public function encrypt($str) {
		$size = mcrypt_get_block_size (MCRYPT_DES,MCRYPT_MODE_CBC);
		$str = $this->pkcs5Pad($str,$size);
		return strtoupper(bin2hex( mcrypt_encrypt(MCRYPT_DES,$this->key,$str,MCRYPT_MODE_CBC,$this->key)));
	}

	/**
	 * @desc 解密
	 * @param string $str
	 * @return string
	 */
	public function decrypt($str) {
		$strBin = $this->hex2bin(strtolower($str));
		$str = mcrypt_decrypt(MCRYPT_DES,$strBin,$this->key);
		$str = $this->pkcs5Unpad($str);
		return $str;
	}
	 
	public function hex2bin($hexData) {
		$binData = '';
		for($i = 0; $i < strlen ($hexData ); $i += 2) {
			$binData .= chr(hexdec(substr($hexData,$i,2)));
		}
		return $binData;
	}

	public function pkcs5Pad($text,$blocksize) {
		$pad = $blocksize - (strlen($text) % $blocksize);
		return $text . str_repeat(chr($pad),$pad);
	}
	 
	public function pkcs5Unpad($text) {
		$pad = ord ($text{strlen($text) - 1});
		if ($pad > strlen($text)) {
			return false;
		}	
		if (strspn($text,chr($pad),strlen($text) - $pad) != $pad) {
			return false;
		}
		return substr($text,-1 * $pad);
	}
	 
}

$obj = new DES();
echo '<pre>';
echo $str = $obj->encrypt('123456');
echo '<br/>========================================<br/>';
echo $obj->decrypt($str);

下面再介绍一下Golang的,这里有篇文章详细的介绍了《Go加密解密之AES》,并附有代码。

Golang:

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/base64"
	"fmt"
)

func main() {
	// DES 加解密
	testDes()
	// 3DES加解密
	test3Des()
}

func testDes() {
	key := []byte("256&#@$M")
	result,err := DesEncrypt([]byte("123456"),key)
	if err != nil {
		panic(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(result))
	hexstr := fmt.Sprintf("%X",result)
	fmt.Println(hexstr)
	origData,err := DesDecrypt(result,key)
	if err != nil {
		panic(err)
	}
	fmt.Println("=======")
	fmt.Println(string(origData))
}

func test3Des() {
	key := []byte("256&#@$Msefiel#fi32lf3e!")
	result,err := TripleDesEncrypt([]byte("123456"),key)
	if err != nil {
		panic(err)
	}
	fmt.Println(base64.StdEncoding.EncodeToString(result))
	origData,err := TripleDesDecrypt(result,key)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(origData))
}

func DesEncrypt(origData,key []byte) ([]byte,error) {
	block,err := des.NewCipher(key)
	if err != nil {
		return nil,err
	}
	origData = PKCS5Padding(origData,block.BlockSize())
	// origData = ZeroPadding(origData,block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block,key)
	crypted := make([]byte,len(origData))
	// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
	// crypted := origData
	blockMode.CryptBlocks(crypted,origData)
	return crypted,nil
}

func DesDecrypt(crypted,err
	}
	blockMode := cipher.NewCBCDecrypter(block,key)
	origData := make([]byte,len(crypted))
	// origData := crypted
	blockMode.CryptBlocks(origData,crypted)
	origData = PKCS5UnPadding(origData)
	// origData = ZeroUnPadding(origData)
	return origData,nil
}

// 3DES加密
func TripleDesEncrypt(origData,err := des.NewTripleDESCipher(key)
	if err != nil {
		return nil,key[:8])
	crypted := make([]byte,len(origData))
	blockMode.CryptBlocks(crypted,nil
}

// 3DES解密
func TripleDesDecrypt(crypted,key[:8])
	origData := make([]byte,nil
}

func ZeroPadding(ciphertext []byte,blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{0},padding)
	return append(ciphertext,padtext...)
}

func ZeroUnPadding(origData []byte) []byte {
	return bytes.TrimRightFunc(origData,func(r rune) bool {
		return r == rune(0)
	})
}

func PKCS5Padding(ciphertext []byte,blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)},padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
	length := len(origData)
	// 去掉最后一个字节 unpadding 次
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

其它几个版本的可以看一下《PHP、JAVA、C#、Object-C 通用的DES加密

这里也顺便Copy一下过来~

C#:

public class MyDes
    {
        /// <summary>
        /// DES加密方法
        /// </summary>
        /// <param name="strPlain">明文</param>
        /// <param name="strDESKey">密钥</param>
        /// <param name="strDESIV">向量</param>
        /// <returns>密文</returns>
        public static string Encode(string source,string _DESKey)
        {
            StringBuilder sb = new StringBuilder();
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                byte[] key = ASCIIEncoding.ASCII.GetBytes(_DESKey);
                byte[] iv = ASCIIEncoding.ASCII.GetBytes(_DESKey);
                byte[] dataByteArray = Encoding.UTF8.GetBytes(source);
                des.Mode = System.Security.Cryptography.CipherMode.CBC;
                des.Key = key;
                des.IV = iv;
                string encrypt = "";
                using (MemoryStream ms = new MemoryStream())
                using (CryptoStream cs = new CryptoStream(ms,des.CreateEncryptor(),CryptoStreamMode.Write))
                {
                    cs.Write(dataByteArray,dataByteArray.Length);
                    cs.FlushFinalBlock();
                    encrypt = Convert.ToBase64String(ms.ToArray());
                }
                return encrypt;
            }
        }
 
        /// <summary>
        /// 进行DES解密。
        /// </summary>
        /// <param name="pToDecrypt">要解密的base64串</param>
        /// <param name="sKey">密钥,且必须为8位。</param>
        /// <returns>已解密的字符串。</returns>
        public static string Decode(string source,string sKey)
        {
            byte[] inputByteArray = System.Convert.FromBase64String(source);//Encoding.UTF8.GetBytes(source);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms,des.CreateDecryptor(),CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray,inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                string str = Encoding.UTF8.GetString(ms.ToArray());
                ms.Close();
                return str;
            }
        }
    }

Object C:

/***  JoDes.h ***/
 
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
 
@interface JoDes : NSObject
 
+ (NSString *) encode:(NSString *)str key:(NSString *)key;
+ (NSString *) decode:(NSString *)str key:(NSString *)key;
 
@end
 
 
/***  JoDes.m ***/
//
//  XLEncrytHelper.m
//  NewHoldGold
//
//  Created by 梁鑫磊 on 13-12-27.
//  Copyright (c) 2013年 zsgjs. All rights reserved.
//
 
#import "JoDes.h"
 
@interface JoDes()
 
+ (NSString *) encodeBase64WithString:(NSString *)strData;
+ (NSString *) encodeBase64WithData:(NSData *)objData;
+ (NSData *) decodeBase64WithString:(NSString *)strBase64;
 
+ (NSString *)doCipher:(NSString *)sTextIn key:(NSString *)sKey
                  context:(CCOperation)encryptOrDecrypt;
 
@end
 
@implementation JoDes
 
+ (NSString *) encode:(NSString *)str key:(NSString *)key
{
    // doCipher 不能编汉字,所以要进行 url encode
    NSMutableString* str1 = [JoDes urlEncode:str];
    NSMutableString* encode = [NSMutableString stringWithString:[JoDes doCipher:str1 key:key context:kCCEncrypt]];
    [JoDes formatSpecialCharacters:encode];
    return encode;
}
 
+ (NSString *) decode:(NSString *)str key:(NSString *)key
{
    NSMutableString *str1 = [NSMutableString stringWithString:str];
    [JoDes reformatSpecialCharacters:str1];
    NSString *rt = [JoDes doCipher:str1 key:key context:kCCDecrypt];
    return rt;
}
 
+ (NSMutableString *)urlEncode:(NSString*)str
{
    NSMutableString* encodeStr = [NSMutableString stringWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    [encodeStr replaceOccurrencesOfString:@"+" withString:@"%2B" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[encodeStr length])];
    [encodeStr replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[encodeStr length])];
    return encodeStr;
}
 
+ (void)formatSpecialCharacters:(NSMutableString *)str
{
    [str replaceOccurrencesOfString:@"+" withString:@"$$" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[str length])];
    [str replaceOccurrencesOfString:@"/" withString:@"@@" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[str length])];
}
 
 
+ (void)reformatSpecialCharacters:(NSMutableString *)str
{
    [str replaceOccurrencesOfString:@"$$" withString:@"+" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[str length])];
    [str replaceOccurrencesOfString:@"@@" withString:@"/" options:NSWidthInsensitiveSearch range:NSMakeRange(0,[str length])];
}
 
+ (NSString *)encodeBase64WithString:(NSString *)strData {
    return [JoDes encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}
 
 
+ (NSString *)encodeBase64WithData:(NSData *)objData {
    NSString *encoding = nil;
    unsigned char *encodingBytes = NULL;
    @try {
        static char encodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        static NSUInteger paddingTable[] = {0,2,1};
         
        NSUInteger dataLength = [objData length];
        NSUInteger encodedBlocks = (dataLength * 8) / 24;
        NSUInteger padding = paddingTable[dataLength % 3];
        if( padding > 0 ) encodedBlocks++;
        NSUInteger encodedLength = encodedBlocks * 4;
         
        encodingBytes = malloc(encodedLength);
        if( encodingBytes != NULL ) {
            NSUInteger rawBytesToProcess = dataLength;
            NSUInteger rawBaseIndex = 0;
            NSUInteger encodingBaseIndex = 0;
            unsigned char *rawBytes = (unsigned char *)[objData bytes];
            unsigned char rawByte1,rawByte2,rawByte3;
            while( rawBytesToProcess >= 3 ) {
                rawByte1 = rawBytes[rawBaseIndex];
                rawByte2 = rawBytes[rawBaseIndex+1];
                rawByte3 = rawBytes[rawBaseIndex+2];
                encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)];
                encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ];
                encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) | ((rawByte3 >> 6) & 0x03) ];
                encodingBytes[encodingBaseIndex+3] = encodingTable[(rawByte3 & 0x3F)];
                 
                rawBaseIndex += 3;
                encodingBaseIndex += 4;
                rawBytesToProcess -= 3;
            }
            rawByte2 = 0;
            switch (dataLength-rawBaseIndex) {
                case 2:
                    rawByte2 = rawBytes[rawBaseIndex+1];
                case 1:
                    rawByte1 = rawBytes[rawBaseIndex];
                    encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)];
                    encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ];
                    encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) ];
                    // we can skip rawByte3 since we have a partial block it would always be 0
                    break;
            }
            // compute location from where to begin inserting padding,it may overwrite some bytes from the partial block encoding
            // if their value was 0 (cases 1-2).
            encodingBaseIndex = encodedLength - padding;
            while( padding-- > 0 ) {
                encodingBytes[encodingBaseIndex++] = '=';
            }
            encoding = [[NSString alloc] initWithBytes:encodingBytes length:encodedLength encoding:NSASCIIStringEncoding];
        }
    }
    @catch (NSException *exception) {
        encoding = nil;
        NSLog(@"WARNING: error occured while tring to encode base 32 data: %@",exception);
    }
    @finally {
        if( encodingBytes != NULL ) {
            free( encodingBytes );
        }
    }
    return encoding;
     
}
 
+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
    NSData *data = nil;
    unsigned char *decodedBytes = NULL;
    @try {
#define __ 255
        static char decodingTable[256] = {
            __,__,// 0x00 - 0x0F
            __,// 0x10 - 0x1F
            __,62,63,// 0x20 - 0x2F
            52,53,54,55,56,57,58,59,60,61,// 0x30 - 0x3F
            __,1,3,4,5,6,7,8,9,10,11,12,13,14,// 0x40 - 0x4F
            15,16,17,18,19,20,21,22,23,24,25,// 0x50 - 0x5F
            __,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,// 0x60 - 0x6F
            41,42,43,44,45,46,47,48,49,50,51,// 0x70 - 0x7F
            __,// 0x80 - 0x8F
            __,// 0x90 - 0x9F
            __,// 0xA0 - 0xAF
            __,// 0xB0 - 0xBF
            __,// 0xC0 - 0xCF
            __,// 0xD0 - 0xDF
            __,// 0xE0 - 0xEF
            __,// 0xF0 - 0xFF
        };
        strBase64 = [strBase64 stringByReplacingOccurrencesOfString:@"=" withString:@""];
        NSData *encodedData = [strBase64 dataUsingEncoding:NSASCIIStringEncoding];
        unsigned char *encodedBytes = (unsigned char *)[encodedData bytes];
         
        NSUInteger encodedLength = [encodedData length];
        NSUInteger encodedBlocks = (encodedLength+3) >> 2;
        NSUInteger expectedDataLength = encodedBlocks * 3;
         
        unsigned char decodingBlock[4];
         
        decodedBytes = malloc(expectedDataLength);
        if( decodedBytes != NULL ) {
             
            NSUInteger i = 0;
            NSUInteger j = 0;
            NSUInteger k = 0;
            unsigned char c;
            while( i < encodedLength ) {
                c = decodingTable[encodedBytes[i]];
                i++;
                if( c != __ ) {
                    decodingBlock[j] = c;
                    j++;
                    if( j == 4 ) {
                        decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
                        decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2);
                        decodedBytes[k+2] = (decodingBlock[2] << 6) | (decodingBlock[3]);
                        j = 0;
                        k += 3;
                    }
                }
            }
             
            // Process left over bytes,if any
            if( j == 3 ) {
                decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
                decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2);
                k += 2;
            } else if( j == 2 ) {
                decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
                k += 1;
            }
            data = [[NSData alloc] initWithBytes:decodedBytes length:k];
        }
    }
    @catch (NSException *exception) {
        data = nil;
        NSLog(@"WARNING: error occured while decoding base 32 string: %@",exception);
    }
    @finally {
        if( decodedBytes != NULL ) {
            free( decodedBytes );
        }
    }
    return data;
     
}
 
 
+ (NSString *)doCipher:(NSString *)sTextIn key:(NSString *)sKey
                  context:(CCOperation)encryptOrDecrypt {
    NSStringEncoding EnC = NSUTF8StringEncoding;
     
    NSMutableData *dTextIn;
    if (encryptOrDecrypt == kCCDecrypt) {
        dTextIn = [[JoDes decodeBase64WithString:sTextIn] mutableCopy];
    }
    else{
        dTextIn = [[sTextIn dataUsingEncoding: EnC] mutableCopy];
    }
    NSMutableData * dKey = [[sKey dataUsingEncoding:EnC] mutableCopy];
    [dKey setLength:kCCBlockSizeDES];
    uint8_t *bufferPtr1 = NULL;
    size_t bufferPtrSize1 = 0;
    size_t movedBytes1 = 0;
    //uint8_t iv[kCCBlockSizeDES];
    //memset((void *) iv,0x0,(size_t) sizeof(iv));
    //    Byte iv[] = {0x12,0x34,0x56,0x78,0x90,0xAB,0xCD,0xEF};
    bufferPtrSize1 = ([sTextIn length] + kCCKeySizeDES) & ~(kCCKeySizeDES -1);
    bufferPtr1 = malloc(bufferPtrSize1 * sizeof(uint8_t));
    memset((void *)bufferPtr1,0x00,bufferPtrSize1);
     
    CCCrypt(encryptOrDecrypt,// CCOperation op
            kCCAlgorithmDES,// CCAlgorithm alg
            kCCOptionPKCS7Padding,// CCOptions options
            [dKey bytes],// const void *key
            [dKey length],// size_t keyLength //
            [dKey bytes],// const void *iv
            [dTextIn bytes],// const void *dataIn
            [dTextIn length],// size_t dataInLength
            (void *)bufferPtr1,// void *dataOut
            bufferPtrSize1,// size_t dataOutAvailable
            &movedBytes1);
     
    //[dTextIn release];
    //[dKey release];
     
    NSString * sResult;
    if (encryptOrDecrypt == kCCDecrypt){
        sResult = [[NSString alloc] initWithData:[NSData dataWithBytes:bufferPtr1 length:movedBytes1] encoding:EnC];
        free(bufferPtr1);
    }
    else {
        NSData *dResult = [NSData dataWithBytes:bufferPtr1 length:movedBytes1];
        free(bufferPtr1);
        sResult = [JoDes encodeBase64WithData:dResult];
    }
    return sResult;
}

Java:

package com.example.aric.test;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
 
import android.util.Base64;
 
public class DES {
 
    public final static String DES_KEY_STRING = "ABSujsuu";
     
    public static String encrypt(String message,String key) throws Exception {
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
 
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
 
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
        cipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);
 
        return encodeBase64(cipher.doFinal(message.getBytes("UTF-8")));
    }
 
    public static String decrypt(String message,String key) throws Exception {
 
        byte[] bytesrc = decodeBase64(message);//convertHexString(message);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
        IvParameterSpec iv = new IvParameterSpec(key.getBytes("UTF-8"));
 
        cipher.init(Cipher.DECRYPT_MODE,iv);
 
        byte[] retByte = cipher.doFinal(bytesrc);
        return new String(retByte);
    }
 
    public static byte[] convertHexString(String ss) {
        byte digest[] = new byte[ss.length() / 2];
        for (int i = 0; i < digest.length; i++) {
            String byteString = ss.substring(2 * i,2 * i + 2);
            int byteValue = Integer.parseInt(byteString,16);
            digest[i] = (byte) byteValue;
        }
 
        return digest;
    }
 
    public static String toHexString(byte b[]) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String plainText = Integer.toHexString(0xff & b[i]);
            if (plainText.length() < 2)
                plainText = "0" + plainText;
            hexString.append(plainText);
        }
 
        return hexString.toString();
    }
 
     
    public static String encodeBase64(byte[] b) {
        return Base64.encodeToString(b,Base64.DEFAULT);
    }
     
    public static byte[] decodeBase64(String base64String) {
        return Base64.decode(base64String,Base64.DEFAULT);
    }
}

相关文章

Golang的文档和社区资源:为什么它可以帮助开发人员快速上手...
Golang:AI 开发者的实用工具
Golang的标准库:为什么它可以大幅度提高开发效率?
Golang的部署和运维:如何将应用程序部署到生产环境中?
高性能AI开发:Golang的优势所在
本篇文章和大家了解一下go语言开发优雅得关闭协程的方法。有...