给文件加解密(openssl 实现)(一)

一、前言

当有重要的敏感数据的时候,给文件和目录额外加一层保护是至关重要的,特别是当需要通过网络与他人传输数据的时候。
给文件加密有多种命令,如gzexe、tar、shc 。在这里我来介绍一下利用tar和openssl来实现加密,并用脚本实现它,以后实现运行一下脚本就行了。
这里介绍使用自己随便写的key文件加解密 和 公钥私钥加解密。

二、openssl 命令

OpenSSL 是一个开源项目,其组成主要包括一下三个组件:

  1. openssl:多用途的命令行工具
  2. libcrypto:加密算法库
  3. libssl:加密模块应用库,实现了ssl及tls

openssl 作为命令行工具,它有多种用途:

version 用于查看版本信息
enc 用于加解密
ciphers 列出加密套件
genrsa 用于生成私钥
rsa RSA密钥管理(例如:从私钥中提取公钥)
req 生成证书签名请求(CSR)
crl 证书吊销列表(CRL)管理
ca CA管理(例如对证书进行签名)
dgst 生成信息摘要
rsautl 用于完成RSA签名、验证、加密和解密功能
passwd 生成散列密码
rand 生成伪随机数
speed 用于测试加解密速度
s_client 通用的SSL/TLS客户端测试工具
X509 X.509证书管理
verify X.509证书验证
pkcs7 PKCS#7协议数据管理

这里只说明一下它作为加密解密作用的选项。

加密解密需要使用的标准命令为 enc ,用法如下:

openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a/-base64]
       [-A] [-k password] [-kfile filename] [-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md]
       [-p] [-P] [-bufsize number] [-nopad] [-debug] [-none] [-engine id]

常用选项有:

-ciphername:对称算法名称,此命令有两种使用方式:-ciphername方式或者省略enc直接使用ciphername。
-in filename:要加密/解密的输入文件,默认为标准输入。
-out filename:要加密/解密的输出文件,默认为标准输出。
-pass arg:输入文件如果有密码保护,指定密码来源。
-e:进行加密操作,默认操作。可以省略
-d:进行解密操作。
-a:使用base64编码对加密结果进行处理。加密后进行base64编码,解密前进行base64解密。
-base64:同-a选项。
-A:默认情况下,base64编码为一个多行的文件。使用此选项,可以让生成的结果为一行。解密时,必须使用同样的选项,否则读取数据时会出错。
-k:指定加密口令,不设置此项时,程序会提示用户输入口令。
-kfile:指定口令存放文件。可以从这个口令存放文件的第一行读取加密口令。
-K key:使用一个16进制的输入口令。如果仅指定-K key而没有指定-k password,必须用-iv选项指定IV。当-K key和-k password都指定时,用-K选项给定的key将会被使用,而使用password来产生初始化向量IV。不建议两者都指定。
-iv IV:手工指定初始化向量(IV)的值。IV值是16进制格式的。如果仅使用-K指定了key而没有使用-k指定password,那么就需要使用-iv手工指定IV值。如果使用-k指定了password,那么IV值会由这个password的值来产生。
-salt:产生一个随机数,并与-k指定的password串联,然后计算其Hash值来防御字典攻击和rainbow table攻击。
rainbow table攻击:用户将密码使用单向函数得到Hash摘要并存入数据库中,验证时,使用同一种单向函数对用户输入口令进行Hash得到摘要信息。将得到的摘要信息和数据中该用户的摘要信息进行比对,一致则通过。考虑到多数人使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向Hash,得到一个摘要组合。然后与数据库中的摘要进行比对即可获得对应的密码。
salt将随机数加入到密码中,然后对一整串进行单向Hash。攻击者就很难通过上面的方式来得到密码。
-S salt:使用16进制的salt。
-nosalt:表示不使用salt。
-z:压缩数据(前提是OpenSSL编译时加入了zip库)。
-md:指定摘要算法。如:MD5 SHA1 SHA256等。
-p:打印出使用的salt、口令以及初始化向量IV。
-P:打印出使用的salt、口令以及IV,不做加密和解密操作,直接退出。
-bufsize number:设置I/O操作的缓冲区大小。因为一个加密的文件可能会很大,每次能够处理的数据是有限的。
-nopad:没有数据填充(主要用于非对称加密操作)。
-debug:打印调试信息。
-none:不对数据进行加密操作。
-engine:指定硬件引擎。

注意: 密码可以用来产生初始化密钥key和初始化向量IV。 新版的OpenSSL必须使用-salt选项。
OpenSSL支持的加密算法:des des3 bf cast cast5 rc2 rc4 rc5 aes等。

三、加密解密脚本

encrypt.sh

#! /bin/sh

# 自己的key文件,加密解密都要用,要保存好
USER_KEY=$1

# 需要加密的文件
ENCRYPT_FILE=$2

PWD=`pwd`/

ENCRYPT_FILE_AES=${PWD}${ENCRYPT_FILE}".aes"
URANDOM_STRING_FILE=${PWD}"urandom.key"
URANDOM_STRING_FILE_ENCRYPT=${PWD}"urandom.des3"


# 加密后生成的文件, 默认pkg结尾
# ENCRYPT_FILE_PKG=${ENCRYPT_FILE}".pkg"
ENCRYPT_FILE_PKG=${PWD}`echo $ENCRYPT_FILE | sed 's/^.*\///' | sed 's/\..*$/_encrypt\.pkg/'`

if [ -f $ENCRYPT_FILE ]; then
    echo "start encrypt file: $ENCRYPT_FILE ..."
else
    echo "$ENCRYPT_FILE is not exists ! exit."
    exit 1
fi

# 随机产生一个key值,并保存到urandom.key
echo "Randomly generate a key value and save it to urandom.key ..."
dd if=/dev/urandom bs=32 count=1 2>/dev/null | hexdump -v -e '/1 "%02X"' > ${URANDOM_STRING_FILE}

# 加密urandom.key, kfile 为自己的key文件,这个key文件解密时也要用
echo "openssl -e urandom.key >> urandom.des3 ..."
openssl enc -e -des3 -a -salt -in ${URANDOM_STRING_FILE} -kfile $USER_KEY -out ${URANDOM_STRING_FILE_ENCRYPT}

# 加密需要加密的文件,kfile为上面产生的urandom.key
openssl enc -e -aes-256-cbc -in ${ENCRYPT_FILE} -kfile ${URANDOM_STRING_FILE} -out ${ENCRYPT_FILE_AES}

# 将 opensslurandom.key而产生的urandom.des3 和
# openssl 加密文件而产生的ENCRYPT_FILE_AES文件
# 一起放入的一个文件中
# 这里urandom.des3的字节长度为122,解密时要记得
cat ${URANDOM_STRING_FILE_ENCRYPT} ${ENCRYPT_FILE_AES} > ${ENCRYPT_FILE_PKG}

echo "output: ${ENCRYPT_FILE_PKG}"

# 删除不需要的文件
rm -f ${ENCRYPT_FILE_AES} ${URANDOM_STRING_FILE} ${URANDOM_STRING_FILE_ENCRYPT}

echo Done.

exit 0

decrypt.sh

#!/bin/sh


USER_KEY=$1

# 需要解密的文件
ENCRYPT_PKG=$2

FILENAME=`echo $ENCRYPT_PKG | sed 's/^.*\///'`

PWD=`pwd`/

ENCRYPT_FILE_AES=${PWD}${FILENAME}".aes"
URANDOM_STRING_FILE=${PWD}"urandom.key"
URANDOM_STRING_FILE_ENCRYPT=${PWD}"urandom.des3"

echo ${ENCRYPT_FILE_AES} ${URANDOM_STRING_FILE} ${URANDOM_STRING_FILE_ENCRYPT}

# 解密后的文件默认是 .tar.gz 类型压缩文件
DECRYPT_FILE=${PWD}`echo ${FILENAME} | sed 's/_encrypt.*$/\.tar.gz/'`

if [ -f $ENCRYPT_PKG ]; then
    echo "start encrypt file: $ENCRYPT_PKG ..."
else
    echo "$ENCRYPT_PKG is not exists ! exit."
    exit 1
fi


dd if=${ENCRYPT_PKG} of=$URANDOM_STRING_FILE_ENCRYPT bs=122 count=1
dd if=${ENCRYPT_PKG} of=${ENCRYPT_FILE_AES} bs=122 skip=1

openssl enc -d -des3 -a -salt -in ${URANDOM_STRING_FILE_ENCRYPT} -kfile ${USER_KEY} -out ${URANDOM_STRING_FILE}
openssl enc -d -aes-256-cbc -in ${ENCRYPT_FILE_AES} -kfile ${URANDOM_STRING_FILE} -out ${DECRYPT_FILE}

rm -f ${ENCRYPT_FILE_AES} ${URANDOM_STRING_FILE} ${URANDOM_STRING_FILE_ENCRYPT}

echo output: ${DECRYPT_FILE}
echo Done.

exit 0


四、测试一下

1
该目录下有文件1.c 和readme,压缩后生成test.tar.gz。我们使用user.key 来对test.tar.gz 加解密。
user.key 是随机字符串文件,不能丢失,否则解密不了。也不能让别人知道。
2
为了看的明白,我们进入enc目录加密,看最后生成了什么
3
目前什么都没,执行…/encrypt.sh …/user.key …/test.tar.gz :
4
生成了test_encrypt.pkg。

再对这个文件解密看看, 进入…/dec/目录,执行…/decrypt.sh …/user.key …/enc/test_encrypt.pkg:
5
OK.


这篇是用自己随便提供的key文件加密解密,那怎么用私钥公钥进行加解密呢,下一篇介绍。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,下面给出VS2008 openssl实现AES加解密字符串的方法。 1. 下载openssl相关库和头文件,并配置好环境变量。 2. 在头文件中引入openssl对应的库文件。 ```c++ #include <openssl/aes.h> ``` 3. 实现AES加密和解密函数,下面分别给出ECB和CBC模式的代码。 ECB模式: ```c++ void AESEncrypt_ECB(const unsigned char *in, const unsigned char *key,unsigned char *out, int length) { AES_KEY aes_key; AES_set_encrypt_key(key, 128, &aes_key); //设置密钥 for (int i = 0; i < length; i += AES_BLOCK_SIZE) { AES_encrypt(in + i, out + i, &aes_key);//加密 } } void AESDecrypt_ECB(const unsigned char *in, const unsigned char *key,unsigned char *out, int length) { AES_KEY aes_key; AES_set_decrypt_key(key, 128, &aes_key); //设置密钥 for (int i = 0; i < length; i += AES_BLOCK_SIZE) { AES_decrypt(in + i, out + i, &aes_key);//解密 } } ``` CBC模式: ```c++ void AESEncrypt_CBC(const unsigned char *in, const unsigned char *key,const unsigned char *iv,unsigned char *out, int length) { AES_KEY aes_key; AES_set_encrypt_key(key, 128, &aes_key); //设置密钥 AES_cbc_encrypt(in, out, length, &aes_key, iv, AES_ENCRYPT); //加密 } void AESDecrypt_CBC(const unsigned char *in, const unsigned char *key,const unsigned char *iv,unsigned char *out, int length) { AES_KEY aes_key; AES_set_decrypt_key(key, 128, &aes_key); //设置密钥 AES_cbc_encrypt(in, out, length, &aes_key, iv, AES_DECRYPT); //解密 } ``` 4. 在主函数中调用上述加解密函数,完整代码如下: ```c++ #include <stdio.h> #include <string.h> #include <openssl/aes.h> //ECB模式加解密 void AESEncrypt_ECB(const unsigned char *in, const unsigned char *key, unsigned char *out, int length) { AES_KEY aes_key; AES_set_encrypt_key(key, 128, &aes_key); //设置密钥 for (int i = 0; i < length; i += AES_BLOCK_SIZE) { AES_encrypt(in + i, out + i, &aes_key);//加密 } } void AESDecrypt_ECB(const unsigned char *in, const unsigned char *key, unsigned char *out, int length) { AES_KEY aes_key; AES_set_decrypt_key(key, 128, &aes_key); //设置密钥 for (int i = 0; i < length; i += AES_BLOCK_SIZE) { AES_decrypt(in + i, out + i, &aes_key);//解密 } } //CBC模式加解密 void AESEncrypt_CBC(const unsigned char *in, const unsigned char *key, const unsigned char *iv,unsigned char *out, int length) { AES_KEY aes_key; AES_set_encrypt_key(key, 128, &aes_key); //设置密钥 AES_cbc_encrypt(in, out, length, &aes_key, iv, AES_ENCRYPT); //加密 } void AESDecrypt_CBC(const unsigned char *in, const unsigned char *key, const unsigned char *iv,unsigned char *out, int length) { AES_KEY aes_key; AES_set_decrypt_key(key, 128, &aes_key); //设置密钥 AES_cbc_encrypt(in, out, length, &aes_key, iv, AES_DECRYPT); //解密 } int main() { //ECB模式下的AES加解密 unsigned char key[16] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70}; char plainText[] = "Hello World"; int length = strlen(plainText); unsigned char padded[length + length % AES_BLOCK_SIZE]; memset(padded, 0, sizeof(padded)); memcpy(padded, plainText, length); AESEncrypt_ECB(padded, key, padded, sizeof(padded)); printf("ECB模式下的AES加密结果: "); for (int i = 0; i < sizeof(padded); i++) { printf("%02X ", padded[i]); } printf("\n"); AESDecrypt_ECB(padded, key, padded, sizeof(padded)); printf("ECB模式下的AES解密结果: %s\n", padded); //CBC模式下的AES加解密 unsigned char iv[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; char plainText1[] = "Hello World"; int length1 = strlen(plainText1); unsigned char padded1[length1 + length1 % AES_BLOCK_SIZE]; memset(padded1, 0, sizeof(padded1)); memcpy(padded1, plainText1, length1); AESEncrypt_CBC(padded1, key, iv, padded1, sizeof(padded1)); printf("CBC模式下的AES加密结果: "); for (int i = 0; i < sizeof(padded1); i++) { printf("%02X ", padded1[i]); } printf("\n"); AESDecrypt_CBC(padded1, key, iv, padded1, sizeof(padded1)); printf("CBC模式下的AES解密结果: %s\n", padded1); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值