openssl 学习之enc中salt参数解析
openssl
传输层安全性/安全套接层及其加密库
项目地址:https://gitcode.com/gh_mirrors/ope/openssl
免费下载资源
·
当我们使用openssl enc 命令工具进行加密的时候,涉及到一个参数 即salt,下面简单分析一下salt参数。salt说白了就是一个随机数,salt与passwd串联,然后计算其hash值来防御dictionary attacks 和预计算的rainbow table 攻击。在openssl 的enc 命令中,通过salt 与passwd 来生加密(解密)密钥和初始向量IV。
一,openssl中enc 中salt相关参数
需要注意的就是,当仅设置-K时,还需要设置IV。
-pass arg
the password source. For more information about the format of arg see the PASS PHRASE ARGUMENTS section in openssl(1).
-salt
use a salt in the key derivation routines. This is the default.
-nosalt
don't use a salt in the key derivation routines. This option SHOULD NOT be used except for test purposes or compatibility with ancient versions of OpenSSL and SSLeay.
-k password
the password to derive the key from. This is for compatibility with previous versions of OpenSSL. Superseded by the -pass argument.
-kfile filename
read the password to derive the key from the first line of filename. This is for compatibility with previous versions of OpenSSL. Superseded by the -pass argument.
-nosalt
do not use a salt
-salt
use salt (randomly generated or provide with -S option) when encrypting (this is the default).
-S salt
the actual salt to use: this must be represented as a string of hex digits.
-K key
the actual key to use: this must be represented as a string comprised only of hex digits. If only the key is specified, the IV must additionally specified using the -iv option. When both a key and a password are specified, the key given with the -K option will be used and the IV generated from the password will be taken. It probably does not make much sense to specify both key and password.
-iv IV
the actual IV to use: this must be represented as a string comprised only of hex digits. When only the key is specified using the -K option, the IV must explicitly be defined. When a password is being specified using one of the other options, the IV is generated from this password.
二,openssl中enc.c 文件分析
enc.c文件是openssl中enc命令对应的源码,我们专注于salt相关参数,故只摘录部分代码。
首先我们来看一下,openssl中调用 EVP_BytesToKey通过passwd和salt来生成Key 和IV,在enc.c 中有如下代码
//line 555 Opensl1.0.1c
EVP_BytesToKey(cipher,dgst,sptr,(unsigned char *)str,
strlen(str),1,key,iv);
//函数原型
//line 115 Evp_key.c Openssl1.0.1c
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const unsigned char *salt, const unsigned char *data, int datal,
int count, unsigned char *key, unsigned char *iv)
通过函数原型,除了str 参数,其他参数我们非常容易看清其意思。我们向前查找,发现各个参数的意思以及具体如何定义的。
1,dgst 为MD5
//line 340~343 Openssl1.0.1c
//摘要算法使用MD5
if (dgst == NULL)
{
dgst = EVP_md5();
2,sptr 为salt
//line513~ 553
if (str != NULL)
{
/* Salt handling: if encrypting generate a salt and
* write to output BIO. If decrypting read salt from
* input BIO.
*/
unsigned char *sptr;
if(nosalt) sptr = NULL;//如果参数制定nosalt 则sptr为NULL
else {
if(enc) {
/**line 270~274 用户指定salt值
**else if (strcmp(*argv,"-S") == 0)
**{
** if (--argc < 1) goto bad;
** hsalt= *(++argv);
**}
**/
if(hsalt) {
if(!set_hex(hsalt,salt,sizeof salt)) {
BIO_printf(bio_err,"invalid hex salt value\n");
goto end;
}
} else if (RAND_pseudo_bytes(salt, sizeof salt) < 0)
goto end;
/* If -P option then don't bother writing */
if((printkey != 2)&& (BIO_write(wbio,magic,
sizeof magic-1) != sizeof magic-1
|| BIO_write(wbio,(char *)salt,sizeof salt) != sizeof salt)) {
BIO_printf(bio_err,"error writing output file\n");
goto end;
}
} else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf
|| BIO_read(rbio,(unsigned char *)salt,sizeof salt) != sizeof salt){
BIO_printf(bio_err,"error reading input file\n");
goto end;
} else if(memcmp(mbuf,magic,sizeof magic-1)) {
BIO_printf(bio_err,"bad magic number\n");
goto end;
}
sptr = salt;
}
3,str为passwd
//line 180~184 Openssl1.0.1c
else if (strcmp(*argv,"-pass") == 0) // passwd 参数,新版本,替代-k
{
if (--argc < 1) goto bad;
passarg= *(++argv);
}//line 223~227 Openssl1.0.1celse
if (strcmp(*argv,"-k") == 0)// passwd 参数,旧版本,建议使用-pass参数
{
if (--argc < 1)
goto bad;
str= *(++argv);
}
//line 414~421 Openssl1.0.1c
if(!str && passarg) {
if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
str = pass;
}
三,EVP_BytesToKey 函数
EVP_BytesToKey函数的功能就是生产key和iv。
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const unsigned char *salt, const unsigned char *data, int datal,
int count, unsigned char *key, unsigned char *iv)
{
EVP_MD_CTX c;
unsigned char md_buf[EVP_MAX_MD_SIZE];
int niv,nkey,addmd=0;
unsigned int mds=0,i;
int rv = 0;
nkey=type->key_len;
niv=type->iv_len;
OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);
if (data == NULL) return(nkey);
EVP_MD_CTX_init(&c);
for (;;)
{
if (!EVP_DigestInit_ex(&c,md, NULL))
return 0;
if (addmd++)
if (!EVP_DigestUpdate(&c,&(md_buf[0]),mds))
goto err;
// 将passwd和salt串联进行hash
if (!EVP_DigestUpdate(&c,data,datal))
goto err;
if (salt != NULL)
if (!EVP_DigestUpdate(&c,salt,PKCS5_SALT_LEN))
goto err;
if (!EVP_DigestFinal_ex(&c,&(md_buf[0]),&mds))
goto err;
for (i=1; i<(unsigned int)count; i++)// 对hash结果再进行count次hash
{
if (!EVP_DigestInit_ex(&c,md, NULL))
goto err;
if (!EVP_DigestUpdate(&c,&(md_buf[0]),mds))
goto err;
if (!EVP_DigestFinal_ex(&c,&(md_buf[0]),&mds))
goto err;
}
i=0;
if (nkey)//设置key
{
for (;;)
{
if (nkey == 0) break;
if (i == mds) break;
if (key != NULL)
*(key++)=md_buf[i];
nkey--;
i++;
}
}
if (niv && (i != mds))//设置IV
{
for (;;)
{
if (niv == 0) break;
if (i == mds) break;
if (iv != NULL)
*(iv++)=md_buf[i];
niv--;
i++;
}
}
if ((nkey == 0) && (niv == 0)) break;
}
rv = type->key_len;
err:
EVP_MD_CTX_cleanup(&c);
OPENSSL_cleanse(&(md_buf[0]),EVP_MAX_MD_SIZE);
return rv;
}
GitHub 加速计划 / ope / openssl
25.12 K
9.99 K
下载
传输层安全性/安全套接层及其加密库
最近提交(Master分支:1 个月前 )
fd39d1c8
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/25095)
2 个月前
ae87c488
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/25095)
2 个月前
更多推荐
已为社区贡献3条内容
所有评论(0)