一、前言

当有重要的敏感数据的时候,给文件和目录额外加一层保护是至关重要的,特别是当需要通过网络与他人传输数据的时候。
给文件加密有多种命令,如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



四、测试一下

java 实现 openssl dgst解密 openssl 加解密_linux


该目录下有文件1.c 和readme,压缩后生成test.tar.gz。我们使用user.key 来对test.tar.gz 加解密。

user.key 是随机字符串文件,不能丢失,否则解密不了。也不能让别人知道。

java 实现 openssl dgst解密 openssl 加解密_ci_02


为了看的明白,我们进入enc目录加密,看最后生成了什么

java 实现 openssl dgst解密 openssl 加解密_shell_03


目前什么都没,执行…/encrypt.sh …/user.key …/test.tar.gz :

java 实现 openssl dgst解密 openssl 加解密_ci_04


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

java 实现 openssl dgst解密 openssl 加解密_加解密_05


OK.


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