關於加解密的問題在網上搜索了很多資料,用JAVA AES和UNIX下OpenSSL各自加解密都沒什麼問題,但是如果要JAVA AES算法的加密文件發送到UNIX下openssl解密,或者UNIX OpenSSL加密的文件發給JAVA AES算法解密可就沒那麼容易了。大家可以先看看 http://www.linuxidc.com/Linux/2015-01/112068.htm 。這篇文章已經講的很清楚了,我也是通過這篇文章實現加解密的,我主要講一下在UNIX下openssl加解密編譯時鏈接庫的問題,也就是makefile的編寫,由於對makefile不太熟悉,所以還是研究了老半天才解決問題,希望碰到跟我遇到一樣的問題也能夠解決。
我先貼出源碼:
aes.c:
/**
build with shell:
gcc -Wall aes.c -lcrypto -o aes
**/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
void encrypt(unsigned char* in, int inl, unsigned char *out, int* len, unsigned char * key){
unsigned char iv[8];
EVP_CIPHER_CTX ctx;
//此init做的僅是將ctx內存 memset為0
EVP_CIPHER_CTX_init(&ctx);
//cipher = EVP_aes_128_ecb();
//原型為int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv)
//另外對於ecb電子密碼本模式來說,各分組獨立加解密,前後沒有關系,也用不著iv
EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, iv);
*len = 0;
int outl = 0;
//這個EVP_EncryptUpdate的實現實際就是將in按照inl的長度去加密,實現會取得該cipher的塊大小(對aes_128來說是16字節)並將block-size的整數倍去加密。
//如果輸入為50字節,則此處僅加密48字節,outl也為48字節。輸入in中的最後兩字節拷貝到ctx->buf緩存起來。
//對於inl為block_size整數倍的情形,且ctx->buf並沒有以前遺留的數據時則直接加解密操作,省去很多後續工作。
EVP_EncryptUpdate(&ctx, out+*len, &outl, in+*len, inl);
*len+=outl;
//余下最後n字節。此處進行處理。
//如果不支持pading,且還有數據的話就出錯,否則,將block_size-待處理字節數個數個字節設置為此個數的值,如block_size=16,數據長度為4,則將後面的12字節設置為16-4=12,補齊為一個分組後加密
//對於前面為整分組時,如輸入數據為16字節,最後再調用此Final時,不過是對16個0進行加密,此密文不用即可,也根本用不著調一下這Final。
int test = inl>>4;
if(inl != test<<4){
EVP_EncryptFinal_ex(&ctx,out+*len,&outl);
*len+=outl;
}
EVP_CIPHER_CTX_cleanup(&ctx);
}
void decrypt(unsigned char* in, int inl, unsigned char *out, unsigned char *key){
unsigned char iv[8];
EVP_CIPHER_CTX ctx;
//此init做的僅是將ctx內存 memset為0
EVP_CIPHER_CTX_init(&ctx);
//cipher = EVP_aes_128_ecb();
//原型為int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv)
//另外對於ecb電子密碼本模式來說,各分組獨立加解密,前後沒有關系,也用不著iv
EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, key, iv);
int len = 0;
int outl = 0;
EVP_DecryptUpdate(&ctx, out+len, &outl, in+len, inl);
len += outl;
EVP_DecryptFinal_ex(&ctx, out+len, &outl);
len+=outl;
out[len]=0;
EVP_CIPHER_CTX_cleanup(&ctx);
}
int main(int argc, char **argv)
{
unsigned char content[400];
unsigned char key[] = "HelloWorld";
unsigned char en[400],de[400],base64[400], base64_out[400];
int len;
memset(content, 0,400);
memset(en, 0, 400);
memset(de, 0, 400);
memset(base64, 0,400);
memset(base64_out, 0, 400);
strcpy(content, "HelloHbnfjkwahgruiep");
printf("%d %s\n", strlen((const char*)content), content);
encrypt(content,strlen((const char*)content), en, &len, key);
int encode_str_size = EVP_EncodeBlock(base64, en, len);
printf("%d %s\n", encode_str_size, base64);
int length = EVP_DecodeBlock(base64_out, base64, strlen((const char*)base64));
//EVP_DecodeBlock內部同樣調用EVP_DecodeInit + EVP_DecodeUpdate + Evp_DecodeFinal實現,但是並未處理尾部的'='字符,因此結果字符串長度總是為3的倍數
while(base64[--encode_str_size] == '=') length--;
decrypt(base64_out, length, de, key);
printf("%d %s\n", strlen((const char*)de), de);
return 0;
}
makefile:
CFLAGS=-g -c -Aa -Ae +DD64
APPLIBS=-L/opt/openssl/0.9.8/lib/hpux64 -lssl -lcrypto -L/usr/lib/hpux64
CC=cc
all: aes
.c.o:
$(CC) $(CFLAGS) $*.c
aes: aes.o
$(CC) -o aes aes.o \
$(APPLIBS) +DD64
clean:
rm -f *.o
aes.c源碼我就不講了,大家可以參照上面那個鏈接裡面的,這裡主要講下makefile裡面的注意點。
makefile文件裡如果沒有-L/opt/openssl/0.9.8/lib/hpux64 -lssl -lcrypto則會拋出以下錯誤:
ld: Unsatisfied symbol "EVP_EncryptInit_ex" in file aes.o
ld: Unsatisfied symbol "EVP_DecryptInit_ex" in file aes.o
ld: Unsatisfied symbol "EVP_CIPHER_CTX_cleanup" in file aes.o
ld: Unsatisfied symbol "EVP_EncodeBlock" in file aes.o
ld: Unsatisfied symbol "EVP_CIPHER_CTX_init" in file aes.o
ld: Unsatisfied symbol "EVP_EncryptFinal_ex" in file aes.o
ld: Unsatisfied symbol "EVP_DecryptFinal_ex" in file aes.o
ld: Unsatisfied symbol "EVP_DecryptUpdate" in file aes.o
ld: Unsatisfied symbol "EVP_EncryptUpdate" in file aes.o
ld: Unsatisfied symbol "EVP_aes_128_ecb" in file aes.o
ld: Unsatisfied symbol "EVP_DecodeBlock" in file aes.o
11 errors.
*** Error exit code 1
這是由於沒有鏈接到openssl庫的原因,那麼大家也就明白加上這句的緣由了。makefile中/opt/openssl/0.9.8/lib/hpux64這個路徑是openssl安裝後庫的所在路徑,路徑下應該有 libcrypto.a libssl.a libcrypto.so libssl.so 這些庫文件。
講了這麼多其實就是對makefile的編寫不熟悉,希望一樣遇到此問題的看到這篇文章後能夠順利解決問題。