自学内容网 自学内容网

AES_ECB算法C++与Java相互加解密Demo

一、AES算法

AES是一种对称加密算法,算法秘钥长度可为128位(16字节)、192位(24字节)、256位(32字节)。加密模式分为ECB、CBC、CTR等,其中ECB模式最简单够用。现给出ECB模式下C++和Java的实现,并且可以相互加解密验证。

二、AES_ECB实现DEMO

2.1 C++版本

#include <string>
#include <vector>
#include <openssl/evp.h>

EVP_CIPHER *getAlgPoint(const int keyLen){
    EVP_CIPHER *pAlg = nullptr;
    if (keyLen <= 16) {
        pAlg = (EVP_CIPHER *)EVP_aes_128_ecb();
    }
    else if (keyLen >16 && keyLen <= 24) {
        pAlg = (EVP_CIPHER *)EVP_aes_192_ecb();
    }
    else{
        pAlg = (EVP_CIPHER *)EVP_aes_256_ecb();
    }
    return pAlg;
}

std::vector<uint8_t> ecbEncrypt(const std::string &key, const std::string &str){
    if (key.empty() || str.empty()) {
        return {};
    }
    
    int encLen = 0;
    int outlen = 0;
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    std::vector<uint8_t > encData(((str.size()/16)+1) * 16);//加密后的长度是16的整数倍,明文刚好16整数倍则密文是明文长度+16字节
    EVP_CipherInit_ex(ctx, getAlgPoint(key.size()), nullptr, (uint8_t*)key.data(), nullptr, 1);
    EVP_CipherUpdate(ctx, encData.data(), &outlen, (const uint8_t *)str.c_str(), (int)str.size());
    encLen = outlen;
    EVP_CipherFinal_ex(ctx, encData.data() + outlen, &outlen);
    encLen += outlen;
    EVP_CIPHER_CTX_free(ctx);
    encData.resize(encLen);
    return encData;
}

std::string ecbDecrypt(const std::string &key, const std::vector<uint8_t> &str){
    if (key.empty() || str.empty()) {
        return "";
    }
    int decLen = 0;
    int outlen = 0;
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    std::vector<uint8_t > decData(str.size());
    EVP_CipherInit_ex(ctx, getAlgPoint(key.size()), nullptr, (uint8_t*)key.data(), nullptr, 0);
    EVP_CipherUpdate(ctx, decData.data(), &outlen, str.data(), (int)str.size());
    decLen = outlen;
    EVP_CipherFinal(ctx, decData.data() + outlen, &outlen);
    decLen += outlen;
    EVP_CIPHER_CTX_free(ctx);
    decData.resize(decLen);
    return std::string((char*)decData.data(), decData.size());
}


 int main(void)
    {
        std::string tKey32 = "12345678901234567890123456789012";
        std::string tSrcMsg = "Hello World!";
        auto byteEnc = ecbEncrypt(tKey32, tSrcMsg);
    
        auto b64Enc = B64::encode(byteEnc.data(), byteEnc.size());//转base64打印加密后的内容, b64转换函数自己实现
        std::cout<<"b64Enc:" << b64Enc <<std::endl;
    
        auto strDec = ecbDecrypt(tKey32, byteEnc);
        std::cout<<"decMsg:"<< strDec<<std::endl;
        
        return 0;
    }
  • demo运行结果
b64Enc:wC/nIjhaktigwT5VfVYXKA==
decMsg:Hello World!

2.2 Java版本

  • AESUtil.java
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;


public class AESUtil {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION_ECB = "AES/ECB/PKCS5Padding";
    private static final String TRANSFORMATION_CTR = "AES/CTR/NoPadding";

    public static String ecbEncrypt(String plainText, String key) throws Exception{
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_ECB);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] eBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(eBytes);
    }

    public static String ecbDecrypt(String encryptedText, String key) throws Exception{
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_ECB);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] dBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        return new String(dBytes, StandardCharsets.UTF_8);
    }

    //ctr模式相比ecb多了初始化向量
    public static String ctrEncrypt(String plainText, String key) throws Exception{
        byte[] iv = new byte[16]; // 初始化向量
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_CTR);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv));
        byte[] eBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(eBytes);
    }

    public static String ctrDecrypt(String encryptedText, String key) throws Exception{
        byte[] iv = new byte[16]; // 初始化向量
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION_CTR);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
        byte[] dBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        return new String(dBytes, StandardCharsets.UTF_8);
    }
}
  • Main.java
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;

public class Main {
    public static void main(String[] args) throws Exception {
        String strkey = "12345678901234567890123456789012";

        String str = "Hello World!";
        String eStr = AESUtil.ecbEncrypt(str, strkey);
        System.out.println("aes256 eStr:" + eStr);

        String dStr = AESUtil.ecbDecrypt(eStr, strkey);
        System.out.println("aes256 dStr:" + dStr);
    }
}
  • demo运行结果
aes256 eStr:wC/nIjhaktigwT5VfVYXKA==
aes256 dStr:Hello World!

C++与Java的运行结果一致,如果测试128、192位秘钥,只用修改main函数中的秘钥长度,其他部分不用改动。


原文地址:https://blog.csdn.net/cugwuhan2014/article/details/143366742

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!