信息摘要算法之六:HKDF算法分析与实现
HKDF是一种特定的键衍生函数(KDF),即初始键控材料的功能,KDF从其中派生出一个或多个密码强大的密钥。在此我们想要描述的是基于HMAC的HKDF。
1、HKDF概述
密钥派生函数(KDF)是密码系统的基本组成部分。它的目标是获取一些初始的密钥材料,并从中派生出一个或多个安全强度很大的密钥。
我们将要介绍的是基于HMAC的KDF,称之为HKDF,它可以应用于各种协议和应用程序的构建。HKDF在逻辑上由两个部分组成。第一个部分采用输入密钥材料和“提取”,它是一个固定长度的伪随机密钥K。第二部分则将密钥扩展为几个随机密钥,并以我们需要的长度输出。
在许多应用程序中,输入的密钥材料不一定是均匀分布的,而且攻击者可能对它有一定的了解,甚至可以部分控制它。因此,“提取”阶段的目标是将输入密钥材料的可能分散的熵“集中”到一个短的,但强度高的伪随机密钥。在某些应用程序中,输入可能已经是一个好的伪随机密钥;在这些情况下,“提取”部分是不必要的,“扩展”部分可以单独使用。
第二阶段“扩展”伪随机密钥到所需的长度;输出密钥的数量和长度取决于所需密钥的具体加密算法。
2、算法描述
HKDF就是利用实例化了的哈希函数的HMAC来实现密钥生成。HMAC有两个必要的参数:第一个是密钥,第二个是输入(或消息)。当消息由几个元素组成时,我们在第二个参数中使用串联(表示|);例如,HMAC(K, elem1|elem2|elem3)。
一般来说,HKDF算法所做的工作分为2步,其一称之为提取;其二称之为扩展。接下来我们说明这两步。
(1)、提取
所谓提取就是将用户输入的密钥尽量的伪随机化。一般是使用一个哈希函数来实现,具体那种更具需要在HMAC中确定。这一过程可以表示如下:
HKDF-Extract(salt, IKM)得到PRK,而PRK的计算公式如下:
PRK = HMAC-Hash(salt, IKM) ,这其中有2个输入和1个输出,
Salt,输入,加盐操作的盐,如果不提供则全部初始化为0的字符串,长度则为所采用哈希函数的散列值长度。
IKM,输入,数额udemiyao材料。
PRK,输出,伪随机化后的密钥,长度则为所采用哈希函数的散列值长度。
需要注意的是,在这一步中“IKM”被用作HMAC输入,而不是HMAC密钥。
(2)、扩展
所谓扩展,其实就是通过一系列的哈希运算将密钥扩展到我们需要的长度。这个长度我们记为L。这一过程标识如下:
HKDF-Expand(PRK, info, L) -> OKM,其中有3个输入量和1个输出量,其中:
PRK,输入,一般是在提取阶段得到的输出,是一个伪随机的密钥,长度不小于所采用的哈希算法的输出摘要长度。
Info,输入,可选上下文和应用程序特定信息(可以是零长度字符串)
L,输入,以字节计算的密钥原料的长度,一般不长于哈希函数输出摘要长度的255倍。
OKM,输出,长度为L的密钥材料输出,其计算方式如下:
计算一系列的哈希值,我们记为T(n),其中n为0-255的整数,具体取值由所计算的长度L来确定。n的最大值为:L除以所用哈希函数输出摘要的长度,再向上取整,我们将其记为N。
T(0) = 长度为0的空字符串
T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
直到T(N)为止,需要注意的是,每个哈希操作都会串接一个字节的常量,从1到N,所以最大的N值只能到255。然后将计算得到的这些T(n)串接起来,我们记为T,即:
T = T(1) | T(2) | T(3) | ... | T(N)
而我们想要获得的OKM正是取T的前L个字节组成。这要我们就得到了我们想要的密钥材料。
3、代码实现
上面我们已经描述了HKDF的实现过程,接下来我们将实现这一过程。首先,我们任然是定义一个上下文结构。
/** 该结构将为HKDF的提取-扩展秘钥派生函数提供上下文信息*/
typedef struct HKDFContext {
int whichSha;
HMACContext hmacContext;
int hashSize;
unsigned char prk[SHAMaxHashSize];
int Computed;
int Corrupted;
} HKDFContext;
接着我们实现HDKF的抽取函数,该函数的实现如下:
int hkdfExtract(SHAversion whichSha,
const unsigned char *salt, int salt_len,
const unsigned char *ikm, int ikm_len,
uint8_t prk[SHAMaxHashSize])
{
unsigned char nullSalt[SHAMaxHashSize];
if (salt == 0)
{
salt = nullSalt;
salt_len = SHAHashSize(whichSha);
memset(nullSalt,'\0',salt_len);
}
else if (salt_len < 0)
{
return shaBadParam;
}
return hmac(whichSha, ikm, ikm_len, salt, salt_len, prk);
}
还需要实现HKDF扩展函数,该函数的实现如下:
int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ], int prk_len,
const unsigned char *info, int info_len,
uint8_t okm[ ], int okm_len)
{
int hash_len, N;
unsigned char T[SHAMaxHashSize];
int Tlen, where, i;
if (info == 0)
{
info = (const unsigned char *)"";
info_len = 0;
}
else if (info_len < 0)
{
return shaBadParam;
}
if (okm_len <= 0) return shaBadParam;
if (!okm) return shaBadParam;
hash_len = SHAHashSize(whichSha);
if (prk_len < hash_len) return shaBadParam;
N = okm_len / hash_len;
if ((okm_len % hash_len) != 0) N++;
if (N > 255) return shaBadParam;
Tlen = 0;
where = 0;
for (i = 1; i <= N; i++)
{
HMACContext context;
unsigned char c = i;
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
hmacInput(&context, T, Tlen) ||
hmacInput(&context, info, info_len) ||
hmacInput(&context, &c, 1) ||
hmacResult(&context, T);
if (ret != shaSuccess) return ret;
memcpy(okm + where, T,(i != N) ? hash_len : (okm_len - where));
where += hash_len;
Tlen = hash_len;
}
return shaSuccess;
}
至此我们就实现了HKDF的全部功能。
4、结果
前面我们已经实现了HKDF,我们还需要对其进行验证,我们采用SHA-256哈希函数,分别生成40位和80为的密钥。
40位密钥:
80位密钥:
很明显,40位的密钥和80位的密钥前40位都是相同的。
欢迎关注:
信息摘要算法之六:HKDF算法分析与实现的更多相关文章
- 信息摘要算法之五:HMAC算法分析与实现
MAC(Message Authentication Code,消息认证码算法)是含有密钥散列函数算法,兼容了MD和SHA算法的特性,并在此基础上加上了密钥.因此MAC算法也经常被称作HMAC算法. ...
- 信息摘要算法之一:MD5算法解析及实现
MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现. ...
- MD5加密算法(信息摘要算法)、Base64算法
1 什么是MD5 信息摘要算法,可以将字符进行加密,每个加密对象在进行加密后都是等长的 应用场景:将用户密码经过MD5加密后再存储到数据库中,这样即使是超级管理员也没有能力知道用户的具体密码是多少:因 ...
- MD5( 信息摘要算法)的概念原理及python代码的实现
简述: message-digest algorithm 5(信息-摘要算法).经常说的“MD5加密”,就是它→信息-摘要算法. md5,其实就是一种算法.可以将一个字符串,或文件,或压缩包,执行md ...
- 信息摘要算法 MessageDigestUtil
package com.xgh.message.digest.test; import java.math.BigInteger; import java.security.MessageDigest ...
- OpenSSL实现了5种信息摘要算法有哪些?
OpenSSL实现了5种信息摘要算法,分别是MD2.MD5.MDC2.SHA(SHA1)和RIPEMD.SHA算法事实上包括了SHA和SHA1两种信息摘要算法.此外,OpenSSL还实现了DSS标准中 ...
- 信息摘要算法之三:SHA256算法分析与实现
前面一篇中我们分析了SHA的原理,并且以SHA1为例实现了相关的算法,在这一片中我们将进一步分析SHA2并实现之. 1.SHA简述 前面的篇章中我们已经说明过,SHA实际包括有一系列算法,分别是SHA ...
- 信息摘要算法之四:SHA512算法分析与实现
前面一篇中我们分析了SHA256的原理,并且实现了该算法,在这一篇中我们将进一步分析SHA512并实现之. 1.SHA简述 尽管在前面的篇章中我们介绍过SHA算法,但出于阐述的完整性我依然要简单的说明 ...
- 信息摘要算法之二:SHA1算法分析及实现
SHA算法,即安全散列算法(Secure Hash Algorithm)是一种与MD5同源的数据加密算法,该算法经过加密专家多年来的发展和改进已日益完善,现在已成为公认的最安全的散列算法之一,并被广泛 ...
随机推荐
- mongodb 添加字段并设置默认值
db.doc名称.update({}, {$set: {新字段名称: 默认值}}, false, true) 如:db.fly_bill.update({}, {$set: {usableStatus ...
- C语言编程程序的内存如何布局
重点关注以下内容: C语言程序在内存中各个段的组成 C语言程序连接过程中的特性和常见错误 C语言程序的运行方式 一:C语言程序的存储区域 由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过 ...
- mariadb开启远程访问
安装好mariadb之后,开启防火墙端口,但是还是远程访问,一顿百度之后,找到原因 使MariaDB允许远程访问 确定服务器上的防火墙没有阻止 3306 端口 使用nestat命令查看3306端口状态 ...
- linux 统计某目录文件的行数
通过find 正则搜索文件 find . -regex '.*\.c\|.*\.h' 每个文件的行数 find . -regex '.*\.c\|.*\.h' | xargs wc -l 显示文件的总 ...
- 【blog】SpringMVC返回RSS格式的XML数据
代码 import com.sun.syndication.feed.rss.Channel; import com.sun.syndication.feed.rss.Content; import ...
- Javascript入门(五)数组操作、循环语句
一.数组与数组操作 <script type="text/javascript"> //数组定义方式 var list1 = new Array(1,2,3); var ...
- python正则表达式获取代理IP网站上的IP地址
import urllib.request import re def open_url(url): req = urllib.request.Request(url) req.add_header( ...
- Ubuntu 16.04 Matlab2015b安装
小白一个,安装过程参考了一大堆教程. 这里记录一下. 一.安装 1) sudo mkdir /media/matlab 2) cd 到下载的镜像文件所在文件夹 3) 挂载镜像: sudo mount ...
- 海马玩模拟器——搭建React Native环境
Visual Studio Emulator for Android 模拟器国内这网络环境不太用,所以使用海马玩模拟器,给大家推荐一下! 下面开始配置环境: 1)下载1.8+JDK,配置JDK环境参考 ...
- VPS上拖文件(Apache配置、SSH)
场景 下载VPS上的文件 命令 Apache配置 yum install httpd -y /etc/rc.d/init.d/httpd start /sbin/iptables -I INPUT - ...