1. 程式人生 > >java使用AES加密,c++使用crypto++解密

java使用AES加密,c++使用crypto++解密

最近在做一個專案,需要用到加密解密,java端用AES加密了,準備把加好密的資料傳送到c++寫的服務端(crypto++開源庫)。搞了幾天,從不會到會,配置差點把我搞瘋了,太它媽的蛋疼。

編譯器:vs2017

我用的是cryptopp-CRYPTOPP_7_0_0這個版本。

當然你也不需要拿到後自己來生成,你也直接可以下載我生成好的lib包和include包

首先要環境配置:

1、下載後解壓。如圖:

2、在檔案裡找到cryptest.sln啟動,如圖:

3、會出現如下圖所示的四個檔案,點選cryptlib右鍵生成。(注:此時你可根據自己的專案需要選擇64還是32生成,也可選擇是生成MT還是MD的)

4、最後把在output下生成的lib檔案拷貝到自己的專案中,並把.h檔案拷貝過去(自己可以建個目錄存放)

5、最後就是在vs裡使用配置路勁(大家都會,就不多說了)。

然後就是程式碼:java程式碼

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;

//import org.apache.commons.codec.binary.Base64;

public class Encryptor {

    /**
     * 字串轉換成十六進位制字串
     */
    public static String str2HexStr(String str) {

        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString();
    }

    /**
     *
     * 十六進位制轉換字串
     */

    public static byte[] hexStr2Bytes(String hexStr) {
        System.out.println("in len :" + hexStr.length());
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        System.out.println("out len :" + bytes.length);
        System.out.println("ddd" + Arrays.toString(bytes));
        return bytes;
    }

    /**
     * bytes轉換成十六進位制字串
     */
    public static String byte2HexStr(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1)
                hs = hs + "0" + stmp;
            else
                hs = hs + stmp;
            // if (n<b.length-1) hs=hs+":";
        }
        return hs.toUpperCase();
    }

    public static String encrypt(String key, String initVector, String value) {
        try {
            System.out.println("key:\t" + Arrays.toString(key.getBytes("UTF-8")));
            System.out.println("iv:\t" + Arrays.toString(initVector.getBytes("UTF-8")));
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            //Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println(Arrays.toString(encrypted));
            //System.out.println("encrypted string: "
            //        + Base64.encodeBase64String(encrypted));

            return byte2HexStr(encrypted);
            //return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String key, String initVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            //byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
            byte[] original = cipher.doFinal(hexStr2Bytes(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String key = "1234567890123456"; // 128 bit key
        String initVector = "0000000000000000"; // 16 bytes IV

        String en = encrypt(key, initVector, "hello world, cryptopp");
        System.out.println(en);
        System.out.println(decrypt(key, initVector, en));
    }
}

編譯執行輸出:

➜  cypherTest javac Encryptor.java
➜  cypherTest java Encryptor
key:    [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54]
iv:    [48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48]
[2, -46, -51, -100, 37, -49, 11, 72, -29, -122, -15, -49, -44, -40, -17, -69, -14, -69, -112, -20, -124, 98, -8, 108, -88, 33, 23, 19, -66, 3, -48, -59]
02D2CD9C25CF0B48E386F1CFD4D8EFBBF2BB90EC8462F86CA8211713BE03D0C5
in len :64
out len :32
ddd[2, -46, -51, -100, 37, -49, 11, 72, -29, -122, -15, -49, -44, -40, -17, -69, -14, -69, -112, -20, -124, 98, -8, 108, -88, 33, 23, 19, -66, 3, -48, -59]
hello world, cryptopp

c++程式碼段

xxx.h檔案

#ifndef CRYPTOPP_H
#define CRYPTOPP_H

#include <iostream>
#include <fstream>
#include <sstream>

#include <cryptopp/aes.h>
#include <cryptopp/filters.h>
#include <cryptopp/modes.h>



class cryptopp {
public:
    static bool init(const std::string& key, const std::string& iv);
    static std::string encrypt(const std::string& inputPlainText);
    static std::string decrypt(const std::string& cipherTextHex);
private:
    static byte s_key[CryptoPP::AES::DEFAULT_KEYLENGTH];
    static byte s_iv[CryptoPP::AES::DEFAULT_KEYLENGTH];
};
#endif

xxxx.cpp檔案

#include "cryptopp.h"

using namespace std;

void print(const string& cipherText) {
    cout << "[";
    for( unsigned int i = 0; i < cipherText.size(); i++ )
    {
        cout << int(cipherText[i]) << ", "  ;
    }
    cout << "]"<< endl;
}

byte cryptopp::s_key[CryptoPP::AES::DEFAULT_KEYLENGTH];
byte cryptopp::s_iv[CryptoPP::AES::DEFAULT_KEYLENGTH];

bool cryptopp::init(const string& key, const string& iv) {
    if (key.size() != CryptoPP::AES::DEFAULT_KEYLENGTH) {
        return false;
    }
    if (iv.size() != CryptoPP::AES::BLOCKSIZE) {
        return false;
    }

    for(int i = 0; i < CryptoPP::AES::DEFAULT_KEYLENGTH; i++) {
        s_key[i] = key[i];
    }
    for(int i = 0; i < CryptoPP::AES::BLOCKSIZE; i++) {
        s_iv[i] = iv[i];
    }
    //memset(s_key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
    //memset(s_iv, 0x00, CryptoPP::AES::BLOCKSIZE);
    return true;
}



string cryptopp::encrypt(const string& plainText)
{
    /*
    if ((plainText.length() % CryptoPP::AES::BLOCKSIZE) != 0) {
        return "";
    }
    */

    string cipherTextHex;
    try {
        string cipherText;
        CryptoPP::AES::Encryption aesEncryption(s_key, CryptoPP::AES::DEFAULT_KEYLENGTH);
        CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, s_iv);
        //CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink( cipherText ), CryptoPP::StreamTransformationFilter::NO_PADDING);
        CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink( cipherText ));
        stfEncryptor.Put( reinterpret_cast<const unsigned char*>( plainText.c_str() ), plainText.length() );
        stfEncryptor.MessageEnd();

        print(cipherText);
        for( unsigned int i = 0; i < cipherText.size(); i++ )
        {
            char ch[3] = {0};
            sprintf_s(ch,sizeof(ch), "%02x",  static_cast<byte>(cipherText[i]));
            cipherTextHex += ch;
        }
    } catch (const std::exception &e) {
        cipherTextHex = "";
    }

    return cipherTextHex;
}

string cryptopp::decrypt(const string& cipherTextHex)
{
    /*
    if(cipherTextHex.empty()) {
        return string();
    }
    if ((cipherTextHex.length() % CryptoPP::AES::BLOCKSIZE) != 0) {
        return string();
    }
    */

    string cipherText;
    string decryptedText;

    unsigned int i = 0;
    while(true)
    {
        char c;
        int x;
        stringstream ss;
        ss<<hex<<cipherTextHex.substr(i, 2).c_str();
        ss>>x;
        c = (char)x;
        cipherText += c;
        if(i >= cipherTextHex.length() - 2)break;
        i += 2;
    }

    try {
        CryptoPP::AES::Decryption aesDecryption(s_key, CryptoPP::AES::DEFAULT_KEYLENGTH);
        CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, s_iv );
        //CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedText ),CryptoPP::StreamTransformationFilter::NO_PADDING);
        CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( decryptedText ));
        stfDecryptor.Put( reinterpret_cast<const unsigned char*>( cipherText.c_str() ), cipherText.size());

        stfDecryptor.MessageEnd();
    } catch (const std::exception &e) {
        decryptedText = "";
    }

    return decryptedText;
}

int main() {
    cryptopp::init("1234567890123456", "0000000000000000");
    string en = cryptopp::encrypt("hello world, cryptopp");
    cout << en << endl;
    cout << cryptopp::decrypt(en) << endl;
}

程式碼編輯輸出:

$./a.out
[2, -46, -51, -100, 37, -49, 11, 72, -29, -122, -15, -49, -44, -40, -17, -69, -14, -69, -112, -20, -124, 98, -8, 108, -88, 33, 23, 19, -66, 3, -48, -59, ]
02d2cd9c25cf0b48e386f1cfd4d8efbbf2bb90ec8462f86ca8211713be03d0c5
hello world, cryptopp