首页 > 编程语言 > AAuto > AAuto调用Crypto API实现des算法
2013
08-29

AAuto调用Crypto API实现des算法

目前AAuto标准库已包含DES算法,请已官方库为准.

微软的Crypto API封装了很多加密算法,可是网上的文档比较少,找到的代码也有错误.以DES算法来说,我试了多种语言\多个在线加密竟然没有2个计算结果是相同的.DES的算法其实比较简单,网上公布的算法却不尽相同.为防止算法出错,我以.net的System.Security.Cryptography为准,然后查了下Crypto API,是包含DES算法的.
C#代码如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace des
{
    class Program
    {

        //默认密钥向量
       // private static byte[] Keys = { 0xEF, 0xAB, 0x56, 0x78, 0x90, 0x34, 0xCD, 0x12 };
        private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
        public static string EncryptDES(string encryptString, string encryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
                byte[] rgbIV = Keys;
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            catch
            {
                return encryptString;
            }
        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
        /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
        public static string DecryptDES(string decryptString, string decryptKey)
        {
            try
            {
                byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey.Substring(0, 8));
                byte[] rgbIV = Keys;
                byte[] inputByteArray = Convert.FromBase64String(decryptString);
                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();
                return Encoding.UTF8.GetString(mStream.ToArray());
            }
            catch
            {
                return decryptString;
            }
        }
        static void Main(string[] args)
        {
            Console.WriteLine(EncryptDES("125521", "abcdefgh"));
        }
    }
}

在有了标准算法做对比的前提下,我找到了计算结果相同的C代码,调用的同样是Crypto API,VC代码如下:

#include "stdafx.h"
#include <windows.h>
#include <atlstr.h>
#include <wincrypt.h>

const BYTE IV[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
DWORD DesEncrypt(CString data, CString password, BYTE* buffer, DWORD bufferLength)
{
	CT2CA passwd(password, CP_UTF8);
	CT2CA secret(data, CP_UTF8);
	DWORD dataLength = strlen(secret);

	if(buffer == NULL || bufferLength < dataLength + 8 - (dataLength % 8) || password.GetLength() < 8) return 0;
	memcpy(buffer, secret, dataLength);

	HCRYPTPROV hProv = NULL;
	HCRYPTKEY hSessionKey = NULL;
	BOOL bResult = TRUE;

	typedef struct
	{
		BLOBHEADER header;
		DWORD cbKeySize;
		BYTE rgbKeyData[8];
	}KeyBlob;
	KeyBlob blob;
	blob.header.bType = PLAINTEXTKEYBLOB;
	blob.header.bVersion = CUR_BLOB_VERSION;
	blob.header.reserved = 0;
	blob.header.aiKeyAlg = CALG_DES;
	blob.cbKeySize = 8;
	memcpy(blob.rgbKeyData, passwd, 8);

	bResult &= CryptAcquireContext(&hProv,NULL, MS_DEF_PROV, PROV_RSA_FULL,0); 
	bResult &= CryptImportKey(hProv, (BYTE*)&blob, sizeof(blob), 0, 0, &hSessionKey);
	bResult &= CryptSetKeyParam(hSessionKey, KP_IV, (BYTE*)IV, 0);

	bResult &= CryptEncrypt(hSessionKey, NULL, TRUE, 0, (BYTE*)buffer, &dataLength, bufferLength);

	bResult &= CryptDestroyKey(hSessionKey);
	bResult &= CryptReleaseContext(hProv, 0);

	return bResult ? dataLength : 0;
}

void _tmain(int argc, _TCHAR* argv[])
{
	BYTE buffer[8];
	int dataLength = DesEncrypt("125521", "abcdefgh", buffer, sizeof(buffer));

	for (int i=0;i<8;i++)
	{
		printf("%02X",buffer[i]);
	}
	getchar();
}

在这份VC代码的基础上,我利用AAuto的crypt标准库,对DES做了封装.作者对crypt封装的比较高级,api隔离的比较好,花了些时间对比代码后,封装成与C#调用方法相似的库.
库位置lib\crypt\des.aau

import crypt;
namespace crypt
SetKeyParam = ::Advapi32.api("CryptSetKeyParam","bool(POINTER hKey,INT blobType,string str,int flag)")
class des{
	ctor( key,iv = '\x12\x34\x56\x78\x90\xAB\xCD\xEF' ) {
		var csp = ..crypt(); 
		var key_blob = {
			struct hdr ={
				BYTE bType;
				BYTE bVersion;
				WORD reserved;
				INT aiKeyAlg;
			};
			INT cbKeySize = #key;
			BYTE rgbKeyData[1024] = key;
		} ;
		
		key_blob.hdr.bType = 8/*_PLAINTEXTKEYBLOB*/;
		key_blob.hdr.bVersion = 2/*_CUR_BLOB_VERSION*/; 
		key_blob.hdr.aiKeyAlg = 0x6601/*_CALG_DES*/;
	   	key_blob.hdr.reserved = 0;
		var ret,hKey = ..crypt.ImportKey( csp.hCryptProv, key_blob,..raw.sizeof(key_blob),null,0,hKey ) ;
		if(!ret)
			return null,..lasterr(,"crypt.ImportKey");
		var ret = ..crypt.SetKeyParam(hKey,1/*_KP_IV*/,iv,0 ); 
		if(!ret)
			return null,..lasterr(,"crypt.SetKeyParam");
		csp.setKey( hKey )
		this = csp;
	};
}

/**intellisense()
crypt.des(.("密钥","密钥向量") = 返回DEScrypt对象
crypt.des() = !crypt_hash.
!crypt_hash.encrypt(.("源数据") = 加密数据
!crypt_hash.decrypt(.("源数据") = 解密数据
end intellisense**/

调用方法:

import crypt.des
import crypt.bin
import console
csp = crypt.des("abcdefgh");
re = csp.encrypt("125521")
console.log("加密数据",crypt.bin.encodeBase64(re))

re2 = csp.decrypt(re)
console.log("解密数据",re2)
最后编辑:
作者:NINE
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。