一、加密算法分类
对称加密算法、不对称加密算法、不可逆加密算法
1、对称加密算法
特点:较早、技术成熟
原理:
数据发信方将明文和加密秘钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去;收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双发都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。
技术特点:
算法公开、计算量小、加密速度快、加密效率高。
不足之处是:交易双发使用相同密钥,安全性得不到保证。此外,每对用户都需要使用被人不知道的唯一的密钥,这会使得密钥管理非常困难。对称加密算法在分布式网络上使用较为困难;在专用网中广泛使用的加密算法有DES、IDEA等。AES
DES、IDEA
2、不对称加密算法
特点:
原理:
不对称加密算法使用两把完全不同但是又是完全匹配的以对钥匙--公钥和私钥。在使用不对称加密算法加密文件时只有匹配的一对公钥和私钥才能完成对明文的加密和解密过程。加密明文时采用公钥加密,解密密文时使用私钥解密,而且发信方知道收信方的公钥,只有收信方才知道自己的私钥。
技术特点:
基本原理是:如果发信方想发送只有收信方才能解读的加密信息,发信方必须首先知道收信方的公钥,然后利用收信方的公钥来加密原文;收信方收到加密密文后,使用自己的私钥才能解密密文。显然,采用不对称加密算法,收发信双方在通信之前,收信方必须将自己早已随机生成的公钥送给发信方,而自己保留私钥。由于不对称算法拥有两个密钥,因而特别适用于分布式系统中的数据加密。
RSA、DSA
3、不可逆加密算法
不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。显然,在这类加密过程中,加密是自己,解密还得是自己,而所谓解密,实际上就是重新加一次密,所应用的“密码”也就是输入的明文。不可逆加密算法不存在密钥保管和分发问题,非常适合在分布式网络系统上使用,但因加密计算复杂,工作量相当繁重,通常只在数据量有限的情形下使用,如广泛应用在计算机系统中的口令加密,利用的就是不可逆加密算法。近年来,随着计算机系统性能的不断提高,不可逆加密的应用领域正在逐渐增大。在计算机网络中应用较多不可逆加密算法的有RSA公司发明的MD5算法和由美国国家标准局建议的不可逆加密标准SHS(Secure Hash Standard:安全杂乱信息标准)等
二、主要的C++算法库
加密解密例子程序:对称加密
RC4.h
#pragma once
#include <Windows.h>
#include <WinNT.h>
typedef unsigned char* LPBYTE;
typedef const unsigned char* LPCBYTE;
class CRC4
{
public:
CRC4(void);
~CRC4(void);
public:
/*
说明:设置RC4加密密钥(加密解密使用同一密钥)
密钥长度为1-256字节
密钥的长度 dwKeyBytes 与明文长度、密钥流的长度没有必然关系
通常密钥的长度取16字节(128比特)
参数:
lpbzKey 密钥
dwBytes 密钥长度
返回:只要NULL != lpbzKey就返回TRUE
*/
BOOL Init(LPCBYTE lpbzKey, DWORD dwKeyBytes);
/*
说明:
加密过程:输入待加密明文 lpbzSrc ,输出密文lpbzDst ;
解密过程:输入待解密密文 lpbzSrc ,输出解密明文lpbzDst 。
输入和输出长度都是 nSrcBytes 字节
lpbzDst 可以等于 lpbzSrc
返回:只要NULL != lpbzSrc && NULL != lpbzDst && 0 != nSrcBytes 就返回TRUE。
*/
BOOL Update(LPBYTE lpbzSrc, LPBYTE lpbzDst, INT64 nSrcBytes);
protected:
int m_nI;
int m_nJ;
BYTE m_bzS[256];
};
RC4.cpp
#include "StdAfx.h"
#include "RC4.h"
CRC4::CRC4(void)
: m_nI(0)
, m_nJ(0)
{
RtlZeroMemory(m_bzS, 256);
}
CRC4::~CRC4(void)
{
}
BOOL CRC4::Init(LPCBYTE lpbzKey, DWORD dwKeyBytes)
{
BOOL bSuccess = FALSE;
if (NULL != lpbzKey && 0 < dwKeyBytes && 256 >= dwKeyBytes)
{
bSuccess = TRUE;
BYTE k[256] = { 0 };
if (256 == dwKeyBytes)
{
RtlCopyMemory(k, lpbzKey, dwKeyBytes);
}
else
{
for (DWORD i = 0; 256 > i; ++i)
{
m_bzS[i] = (BYTE)i;
k[i] = lpbzKey[i % dwKeyBytes];
}
}
int j = 0;
BYTE temp = 0;
for (int i = 0; 256 > i; ++i)
{
j = (j + m_bzS[i] + k[i]) % 256;
temp = m_bzS[i];
m_bzS[i] = m_bzS[j];
m_bzS[j] = temp;
}
m_nI = m_nJ = 0;
}
return bSuccess;
}
BOOL CRC4::Update(LPBYTE lpbzSrc, LPBYTE lpbzDst, INT64 nSrcBytes)
{
BOOL bSuccess = FALSE;
if (NULL != lpbzSrc && NULL != lpbzDst && 0 < nSrcBytes)
{
bSuccess = TRUE;
BYTE temp = 0;
for (INT64 x = 0; x < nSrcBytes; ++x)
{
m_nI = (m_nI + 1) % 256;
m_nJ = (m_nJ + m_bzS[m_nI]) % 256;
temp = m_bzS[m_nI];
m_bzS[m_nI] = m_bzS[m_nJ];
m_bzS[m_nJ] = temp;
int t = (m_bzS[m_nI] + m_bzS[m_nJ]) % 256;
lpbzDst[x] = lpbzSrc[x] ^ m_bzS[t];
}
}
return bSuccess;
}
main.cpp
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdio.h>
#include <locale.h>
#include <iostream>
#include <string>
#include "RC4.h"
const unsigned char EncryptKey[16] = {'H','e','l','l','o',' ','W','o','r','l','d','!','1','2','3','4'};
int main()
{
std::string strMsgEn, strMsgDe;
std::string strMsg = "AbcD中国@#¥%+-12233";
std::cout << "明文:" << strMsg << std::endl;
CRC4 objCR4;
size_t nLen = strMsg.length();
//加密
objCR4.Init((LPCBYTE)EncryptKey, sizeof(EncryptKey));
BYTE* pbDest = new BYTE[nLen + 1];
memset(pbDest, 0, strMsg.length() + 1);
if (TRUE == objCR4.Update((LPBYTE)strMsg.c_str(), pbDest, nLen));
{
strMsgEn = (char*)pbDest;
std::cout << "密文:" << strMsgEn << std::endl;
}
//解密
BYTE* pbDest2 = new BYTE[nLen + 1];
memset(pbDest2, 0, nLen + 1);
objCR4.Init((LPCBYTE)EncryptKey, sizeof(EncryptKey));//每次加密解密前都需要初始化
if (TRUE == objCR4.Update((LPBYTE)strMsgEn.c_str(), pbDest2, nLen))
{
strMsgDe = (char*)pbDest2;
std::cout << "解密:" << strMsgDe << std::endl;
}
delete[]pbDest;
delete[]pbDest2;
system("pause");
return 0;
}
//明文:AbcD中国@#¥%+-12233
//密文:, }e鍴 扎; 雮7尉u蝲
//解密:AbcD中国@#¥%+-12233