利用Openssl编写加解密逻辑

openssl提供了强大的加解密功能,本文利用openssl实现了一个AES_128_CBC功能,结果用base64编码输出。
代码如下:

#include <openssl/hmac.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <unistd.h>
#include <sys/types.h>
#include <android/log.h>
#include <linux/binder.h>
#include <stdio.h>
#include <stdlib.h>
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <sys/system_properties.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/stat.h>
#include <sys/stat.h>
/* Encode a string to base64 and return it */
int base64_encode(char *string, int length,char *encode)
{
  BIO *bmem=NULL, *b64=NULL;
  BUF_MEM *bptr=NULL;
  b64 = BIO_new(BIO_f_base64());
  bmem = BIO_new(BIO_s_mem());
  b64 = BIO_push(b64, bmem);
  BIO_write(b64, string, length);
  BIO_flush(b64);
  BIO_get_mem_ptr(b64, &bptr);
  sprintf(encode, "%s", bptr->data);
  encode[bptr->length-1] = '\0';
  BIO_free_all(b64);
  return bptr->length-1;
}

/* Decode a string to plain text and return it */
int base64_decode(unsigned char *input, int length,unsigned char* output)
{
        BIO *b64, *bmem;

        //char *buffer = (char *)malloc(strlen(input));
        //memset(buffer, 0, length);

        b64 = BIO_new(BIO_f_base64());
        bmem = BIO_new_mem_buf(input, length);
        bmem = BIO_push(b64, bmem);

        BIO_read(bmem, output, length);

        BIO_free_all(bmem);
        return strlen(output);
}

int encrypt_base64(const unsigned char *key,const unsigned char *plaintext,int plaintext_len,unsigned char *out_base64)
{
  unsigned char out[2000]="\0";
  int outlen, flen, total =0;

  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);

  const EVP_CIPHER *cipher = EVP_aes_128_cbc();
  char iv[16]={12, 34, 56, 78, 90,87, 65, 43,23,54,18,9,4,23,5,6};
  //unsigned char iv[16]="\0";
  printf("key is %s\n",key);

  if(!EVP_EncryptInit(&ctx, cipher, key, iv)){
      return -1;//error
  }

  if(!EVP_EncryptUpdate(&ctx, out, &outlen, plaintext, plaintext_len)){
      return -1;
  }
  EVP_CIPHER_CTX_cleanup(&ctx);
  printf("outlen is %d\n",outlen);
  outlen +=flen;
  printf("flen is %d\n",flen);
  printf("outlen is %d\n",outlen);
  int i=0;
  for(i=0;i<outlen;i++){
      printf("%02x",out[i]);
  }
  printf("\n");
  total = base64_encode(out,outlen,out_base64);
  if(total <= 1)//encode error
    return 0;
  return total;
}

int decrypt_base64(const unsigned char *key,const unsigned char *cipher_text_base64,unsigned char *de)
{
  int ret;
  EVP_CIPHER_CTX ctx2;
  const EVP_CIPHER *cipher;
  int i,len,inl,outl,total=0;
  unsigned char iv[16]={12, 34, 56, 78, 90,87, 65, 43,23,54,18,9,4,23,5,6};
  unsigned char cipher_text[2000];
  int base64_decode_len = base64_decode((unsigned char *)cipher_text_base64,strlen(cipher_text_base64),cipher_text);
  printf("base64_decode_len is %d\n",base64_decode_len);
  LOGI("base64_decode_len=%d\n",base64_decode_len);
  if(base64_decode_len == -1)
  {
    LOGI("err base64_decode_len = %d\n",base64_decode_len);
    return -1;
  }
  cipher=EVP_aes_128_cbc();
  EVP_CIPHER_CTX_init(&ctx2);
  ret=EVP_DecryptInit_ex(&ctx2,cipher,NULL,key,iv);
  if(ret!=1)
  {
    LOGI("EVP_DecryptInit_ex err1!\n");
    return -1;
  }
  total=0;
  EVP_DecryptUpdate(&ctx2,de+total,&outl,cipher_text,base64_decode_len);
  total+=outl;
  if(ret!=1)
  {
    EVP_CIPHER_CTX_cleanup(&ctx2);
    LOGI("EVP_DecryptFinal_ex err\n");
    return -1;
  }
  de[128] = '\0';
   LOGI("de=%s;\n",de);
  EVP_CIPHER_CTX_cleanup(&ctx2);
  return 1;
}

int main(){
    unsigned char key2[33]= "1234567890123455";
    unsigned char in[129]= "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678";
    unsigned char out_base64[512] = "\n";
    unsigned char de[129]="\0";
    encrypt_base64(key2,in,strlen(in),out_base64);
    printf("out_base64=%s\n",(char *)out_base64);
    decrypt_base64(key2,out_base64,de);
    printf("de=%s\n",(char *)de);
    return 0;
}

另外说明一下:EVP_EncryptFinal并不是随便用的,只有一串字符不是16的倍数,后面需要padding时,调用EVP_EncryptFinal去处理最后一串字符的时候才用。而且base64字符串要是超过一定长度,会自动拼接回车的。
执行的结果如下:

root@generic_x86:/data/data # ./encryption
./encryption
key is 1234567890123455
outlen is 128
flen is 0
outlen is 128
1d9d9d361719819cf6383d78059ae1214a19253b64311d851fcfa96a8d109f3d9c9688ab4f1bf97201df6f8854de86ce522f583e92a4b965d496ce74bbf788af7fceff12e9ce9e96fe695c40ec47d203a8d07e515199abe4981167bca4c7c97234fffcbcef02d5b5d75335c2bd801c776ede4ba48e134f8a5efaef974050
6784
out_base64=HZ2dNhcZgZz2OD14BZrhIUoZJTtkMR2FH8+pao0Qnz2cloirTxv5cgHfb4hU3obO
Ui9YPpKkuWXUls50u/eIr3/O/xLpzp6W/mlcQOxH0gOo0H5RUZmr5JgRZ7ykx8ly
NP/8vO8C1bXXUzXCvYAcd27eS6SOE0+KXvrvl0BQZ4Q=
base64_decode_len is 128
de=12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678

你可能感兴趣的:(代码,编码,解密,OpenSSL,base)