我正在尝试以高速方式执行AES。当我使用以下命令执行openssl速度测试时,我得到以下结果:
$ openssl speed -elapsed -evp aes-128-cbc
You have chosen to measure elapsed time instead of user CPU time.
Doing aes-128-cbc for 3s on 16 size blocks: 224201744 aes-128-cbc's in 3.00s
Doing aes-128-cbc for 3s on 64 size blocks: 62982851 aes-128-cbc's in 3.00s
Doing aes-128-cbc for 3s on 256 size blocks: 16102515 aes-128-cbc's in 3.00s
Doing aes-128-cbc for 3s on 1024 size blocks: 4052200 aes-128-cbc's in 3.00s
Doing aes-128-cbc for 3s on 8192 size blocks: 510962 aes-128-cbc's in 3.00s
OpenSSL 1.0.2n 7 Dec 2017
built on: reproducible build, date unspecified
options:bn(64,64) rc4(16x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx)
compiler: gcc -I. -I.. -I../include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DRC4_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
The 'numbers' are in 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
aes-128-cbc 1195742.63k 1343634.15k 1374081.28k 1383150.93k 1395266.90k
这意味着 128 位块的每个 AES 加密速度应为 1.32 ns。但是当我执行以下使用 openssl 和 EVP 的C++代码时,性能变为 217 ns:
#include <stdio.h>
#include <openssl/evp.h>
#include <chrono>
#include <iostream>
using namespace std;
int main()
{
EVP_CIPHER_CTX ctx;
unsigned char key[16] = {0};
unsigned char iv[16] = {0};
unsigned char in[16] = {0};
unsigned char out[16]; /* at least one block longer than in[] */
int outlen1, outlen2;
std::chrono::time_point<std::chrono::high_resolution_clock> m_beg = std::chrono::high_resolution_clock::now();
for(int z=0;z<10000;z++){
EVP_EncryptInit(&ctx, EVP_aes_128_cbc(), key, iv);
EVP_EncryptUpdate(&ctx, out, &outlen1, in, sizeof(in));
EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);
}
double t = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_beg).count();
cout<<t<<endl;
printf("ciphertext length: %dn", outlen1 + outlen2);
return 0;
}
有谁知道问题出在哪里?
这是我的发布制作文件:
# Environment
MKDIR=mkdir
CP=cp
GREP=grep
NM=nm
CCADMIN=CCadmin
RANLIB=ranlib
CC=gcc
CCC=g++
CXX=g++
FC=g++
AS=as
# Macros
CND_PLATFORM=GNU-Linux
CND_DLIB_EXT=so
CND_CONF=Release
CND_DISTDIR=dist
CND_BUILDDIR=build
# Include project Makefile
include Makefile
# Object Directory
OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}
# Object Files
OBJECTFILES=
${OBJECTDIR}/main.o
# C Compiler Flags
CFLAGS=
# CC Compiler Flags
CCFLAGS=
CXXFLAGS=
# Fortran Compiler Flags
FFLAGS=
# Assembler Flags
ASFLAGS=
# Link Libraries and Options
LDLIBSOPTIONS=
# Build Targets
.build-conf: ${BUILD_SUBPROJECTS}
"${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/aes_ni_test
${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/aes_ni_test: ${OBJECTFILES}
${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}
${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/aes_ni_test ${OBJECTFILES} ${LDLIBSOPTIONS} -lcrypto
${OBJECTDIR}/main.o: main.cpp
${MKDIR} -p ${OBJECTDIR}
${RM} "$@.d"
$(COMPILE.cc) -O3 -std=c++14 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/main.o main.cpp
# Subprojects
.build-subprojects:
# Clean Targets
.clean-conf: ${CLEAN_SUBPROJECTS}
${RM} -r ${CND_BUILDDIR}/${CND_CONF}
# Subprojects
.clean-subprojects:
# Enable dependency checking
.dep.inc: .depcheck-impl
include .dep.inc
原因是 c++ 代码中 AES 的 INIT 和 FINAL 部分。OPENSSL 命令不会针对每次加密执行它。因此,它的性能要高得多。