《略说USB Key》之算法和接口标准

作者:王永龙

http://www.wangyonglong.com/2012/11/%E3%80%8A%E7%BB%86%E8%AF%B4usb-key%E3%80%8B%E4%B9%8B%E7%AE%97%E6%B3%95%E5%92%8C%E6%8E%A5%E5%8F%A3%E6%A0%87%E5%87%86/


1、密码及算法

算法是UKey产品的核心,也是进行身份认证、数据加、解密的核心。在UKey中会涉及到是算法分成三类:摘要算法、对称算法和非对称算法。其中,摘要算法不存在密码(也称密钥)。对称和非对称算法需要密码的参与。

摘要算法又称为哈希算法(HASH)。摘要算法的功能,就是将一长串数据(无论多长)变换成一个固定长度的数据串。对于某一个特定的摘要算法,它具有的特点是,给定一个原始数据串A,它总能计算出一个固定长度的数据串B。也就是说如果算法固定,由A总能计算出B。而给定B,确不能由此计算得出A。A是一个不固定长度的数据串,而B却是固定长度的。说到这里,我们不得不产生一个疑惑:由于B的长度固定,那么B的排列组合一定是有限次的,但A由于不确定长度,那么A是个无限的集合,B是个有限集合。既然通过摘要算法,某一个A一定能得到一个确定的B,而B是有限的,那么就存在一个可能,就是存在两个或两个以上(甚至是无穷多的)的原始数据串A1,A2,...An,它们通过固定的摘要算法f,能都计算得出同一个数据串B。这是毫无疑问的。我们将此时A1,A2,...An它们之间的关系称之为碰撞。

虽然摘要算法的碰撞是存在的,但却并不影响我们接下来的运算。

通常我们使用的摘要算法有:MD5、SHA1、SHA256、SHA512等。MD5是我们所熟悉的摘要算法,通过MD5,我们可以将一个不固定长度的数据串加工成一个只有16个字节长度的固定数据串。此外,国家密码管理局还研制了国产摘要算法SM3。SM3通常和国产椭圆曲线算法SM2一起使用,SM3计算出来的Hash串的长度为20个字节。关于SM3的算法细节请参考国家密码管理局网站公布的算法文档。其他的摘要算法都可以从网络上或者相关教材中得到详细的介绍。

对称算法是指加密过程和解密过程所使用的密码是同一个密码。对称算法也是加解密算法史上重要的里程碑。在过去的敌特电影中,我们通常会看到一个叫做密码本的东西。密码本就相当于对称密钥。掌握了密码本,就掌握了对方的秘密,因为在发送密文前,要用密码本上的文字置换原始文字(原文)变成密文。拿到密文之后,也要用同一个密码本来解开密文从而得到原文。所以获取密码本是破解密文最关键的一环。同时也暴露除了对称算法的一个缺点,就是要让加解密的双方都知道同一个密钥。这就涉及到密钥的传递。这是一个相当不安全的因素。在战争年代,为了安全的传递对称密码(密码本),可能会付出巨大的代价,甚至是生命。

对于要普及对称算法来说,还有一个巨大的问题,就是密码的管理。设想我们每个人都需要跟别人传递密文,而密钥只能是仅能由双方知道,否则第三个人就可能知道我们之间传递的内容了,这种情况下,如果有两个人,就会需要1个密钥,如果有三个人,则需要3个密钥,如果四个人,则需要6个密钥,那么如果是n个人,就需要{[n(n-1)]/2}个密钥,假如有1万个人需要相互发送密文,需要的密钥量就是49995000个不同的密钥,这个量实在是太大了,无论在管理,传递方面都是一个巨大的负担,而且存在着很大的传递风险!

对称算法也有它的优势。现代加解密的算法绝大部分都是分组处理的。在对称算法中,通常的一个分组为8个字节,也就是说每8个字节进行一次加密或者解密。分组处理完成之后再按照线性存放即可。对称算法可以在速度这方面做到极致,它的分组处理可以并发进行,因此运算十分高效,在对比非对称算法处理方面,对称算法的速度性是个无可比拟的优势所在。通过巧妙的程序设计,可以将加密或者解密做成一个模块,或软件,或硬件,在实际使用中通过并发计算,能达到极高的速度。通常我们在评估可信计算模块或者芯片的性能的时候,对于对称算法,每秒可计算的数据量是一个重要的指标。

通常使用的对称算法有:DES、3DES、AES。国家密码管理局此前推广的国产对称算法有SSF33、SCB2。后来经过发展,SSF33逐渐淡出,SCB2更名为SM1。除此之外,还推出了算法公开的SM4等。

随着计算技术的发展,CPU的升级,对称算法也存在破解的可能,例如,目前破解DES算法的可能性就大大提高了。在1997年、1998年、1999年美国都举办了DES密码破解的竞赛。当时分别通过多机分布式计算,单机高性能计算以及耗时数月的计算后都找到了相应的密钥。为了提高对称算法的破解难度,数学家在此后发展了3DES,将密钥长度扩展到24个字节(实际是21个字节,DES使用56bits为密钥)。3DES意味着一个8Bytes的分组数据,要经过3次DES运算,而且每次运算的密钥还各不相同,最后计算出来一个分组密文。由于密钥空间变大了,3DES的安全性得到大大提高。

此外,数学家还对加解密时的数据分组方式进行了扩展。在最早我们使用最原始,效率最高的电子密码本模式(ECB)。也就是在加密时是按照固定分组进行的,只要原文分组好了,完全可以并发运算,效率极高。后来为了加大破解的难度,设计了密码分组链接模式(CBC)。在这种方式下,第一个分组运算出来的密文要跟第二个分组进行异或然后再进行加密,因此这是一种链式加密,在没有完成第一个分组的加密时,无法进行第二个分组的加密。这种模式增加了破解难度,但效率大大降低了。除此之外,还有密码反馈模式(CFB),CFB是设计为流式加密服务的,分组加密后输出的密文要按照一个字节一个字节发送出去,同时原文向前移动一个字节,最低位的字节要与发送的该字节进行异或并替换该原明文字节,然后再对这个移动了一个字节的分组进行加密,再输出一个加密字节,依次渐进。还有一种分组方式叫做输出反馈模式(OFB)。OFB类似于CFB,但反馈到原文的是加密后的密文的若干bits,且并不需要跟原文的某些bits进行异或处理。以上这些复杂的分组模式的具体过程,可以参考相关的密码学教科书,如《现代密码学教程》等。如学习时对照教科书上的内容,并参考一些加密算法的实现代码,能有助于理解算法处理的过程。

我认为非对称算法是算法界的一个了不起的创举。由于非对称算法的开创,催生了CA这一类身份证书管理机构;由于有了证书,在互联网上可以实现安全的链接和数据传输规范,这大大刺激了互联网的发展壮大。非对称算法又称为公钥密码算法。RSA算法是历史上第一个能正式大规模应用的非对称算法。RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA也是目前最有影响力的公钥加密算法。

非对称算法的本质就是加密和解密的密码是不同的,比如加密用密码k1,那么会存在一个密码k2,可以用来解密。同样的,用k2做加密,也只能用k1来解密。k1和k2之间符合某种数学关系。但要想从k1推导出k2对于简单的机构组织而言,几乎是不可能的。比如某人拥有一对密码,分别是k1和k2,他可以选择将k1公之于众,而k2则作为个人机密为个人私有。那么在这种情况下,可以完成在网络通信下的两种重要的过程。1)数据加密。由于k1公开了,所以别人要给你发送私密信息,只需要用k1加密即可,全世界只有你的k2能解开;2)身份认证。由于k1公开,且被认证未你的公开密码,那么对应的就有你自己保管的k2,这个时候,你要想给某人发一个公函文件,只要用k2加密,对方用k1来解开的时候,就知道这个公函一定是你签发的了。这就实现了一个身份认证的功能。

2、PKCS#11接口标准

RSA非对称密码算法的三个创始人的姓的第一个字母联合起来就是RSA了,他们三个创建的公司的名字也就叫做RSA。在RSA有一个著名的公钥算法的实验室,这个实验室颁发的一系列行业标准就称作为PKCS标准,其中PKCS#11(简称P11)就是针对密码设备的接口指令标准。目前最新的版本应该是2.3了。

P11模型中重要的概念之一是slot,也称为槽。一个slot为一个密码设备对象。某个打开的slot会话称之为session。Session之间存在不同的验证权限。而同一个slot的不同的session之间存在操作的互相影响性,同时在某些状况下,权限会发生同步。另外一个重要的概念是对象。P11中支持几种重要的对象,如公钥、私钥、对称密钥,数据对象等。

PKCS#11创建和支持下列对象:

对象 说明
CKO_DATA 应用程序定义的对象。对象的数据结构可由应用程序任意定义,但是数据意义的解释由应用程序负责。
CKO_SECRET_KEY 对称加密算法使用的密钥。
CKO_CERTIFICATE X.509
CKO_PUBLIC_KEY RSA
CKO_PRIVATE_KEY RSA
CKO_MECHANISM 算法对象

 

PKCS#11的对象可根据其生命期长短的不同分成两大类:一类是持久存储的类对象,这类对象被保存在USB Key的安全存储区域当中,直到应用程序主动删除这些对象;另一类是会话对象,这类对象只存在于运行时建立的特定会话(Session对象)当中,一旦会话结束,这类对象也跟着被删除。决定对象生命期的模板属性是CKA_TOKEN,这是个布尔值,所有的对象都有这一属性。当该值为TRUE时,该对象将被保存到Key内的存储空间,否则,该对象保存在会话空间中,当会话结束后,该对象即销毁。

PKCS#11的对象除了生命期长短有分别之外,在访问权限上也有限制。所有的对象都可根据访问权限的不同分成两大类:一类是公开对象,这类对象是任何用户都可以访问的;另一类是私有对象,这一类对象只有身份被验证的用户才有权访问。决定对象的访问限制类型的模板属性是CKA_PRIVATE。这是个布尔值,所有的对象都有这一属性。应用程序可根据需要决定对象应为私有对象还是公开对象。

P11标准颁发了70余条指令。其中部分指令简介如下表:

接口类型 函数名称 描述
通用接口函数 C_Initialize 初始化 Cryptoki
C_Finalize 整理各种适合 Cryptoki的资源
C_GetInfo 获得关于Cryptoki的通用信息
C_GetFunctionList 获得Cryptoki 库函数的进入点
槽和令牌管理函数 C_GetSlotList 获得系统中槽的名单
C_GetSlotInfo 获得关于特殊槽的信息
C_GetTokenInfo 获得关于特殊令牌的信息
C_WaitForSlotEvent 等待槽事件(令牌插入,转移等) 的发生
C_GetMechanismList 获得由令牌支持的机制的名单
C_GetMechanismInfo 获得关于特殊机制的信息
C_InitToken 初始化一个令牌
C_InitPIN 初始化普通用户的 PIN
C_SetPIN 改变现在用户的PIN
会话管理函数 C_OpenSession 打开一个应用程序和特殊令牌之间的连接或安装一个应用程序呼叫返回令牌插入
C_CloseSession 关闭一个会话
C_CloseAllSessions 用令牌关闭所有的会话
C_GetSessionInfo 获得关于会话的信息
C_GetOperationState 获得会话的加密操作状态
C_SetOperationState 设置会话的加密操作状态
C_Login 注册一个令牌
C_Logout 从一个令牌注销
对象管理函数 C_CreateObject 建立一个对象
C_CopyObject 建立一个对象的拷贝
C_DestroyObject 销毁一个对象
C_GetObjectSize 获取字节中一个对象的大小
C_GetAttributeValue 获取一个对象的属性值
C_SetAttributeValue 改变一个对象的属性值
C_FindObjectsInit 初始化一个对象的搜索操作
C_FindObjects 继续一个对象搜索操作
C_FindObjectsFinal 完成一个对象搜索操作
加密函数 C_EncryptInit 初始化一个加密操作
C_Encrypt 加密单部分数据
C_EncryptUpdate 继续一个多部分加密操作
C_EncryptFinal 完成一个多部分加密操作
解密函数 C_DecryptInit 初始化一个解密操作
C_Decrypt 解密单部分加密数据
C_DecryptUpdate 继续一个多部分解密操作
C_DecryptFinal 完成一个多部分解密操作
消息解密函数 C_DigestInit 初始化一个消息摘要操作
C_Digest 摘要单部分数据
C_DigestUpdate 继续一个多部分摘要操作
C_DigestKey 摘要一个密钥
C_DigestFinal 完成一个多部分摘要操作
签名和消息鉴别函数 C_SignInit 初始化一个签名操作
C_Sign 签名单部分数据
C_SignUpdate 继续一个多部分签名操作
C_SignFinal 完成一个多部分签名操作
C_SignRecoverInit 初始化一个签名操作,在操作中数据能从签名中恢复
C_SignRecover 签名单部分数据,在操作中数据能从签名中恢复
签名鉴定消息鉴别函数 C_VerifyInit 初始化一个鉴定操作
C_Verify 在单部分数据上鉴定一个签名
C_VerifyUpdate 继续一个多部分鉴定操作
C_VerifyFinal 完成一个多部分鉴定操作
C_VerifyRecoverInit 初始化一个鉴定操作,在操作中数据能从签名中恢复
C_VerifyRecover 在单部分数据上鉴定一个签名,在操作中数据能从签名中恢复
双效加密函数 C_DigestEncryptUpdate 继续类似的多部分摘要和加密操作
C_DecryptDigestUpdate 继续类似的多部分解密和摘要操作
C_SignEncryptUpdate 继续类似的多部分签名和加密操作
C_DecryptVerifyUpdate 继续类似的多部分解密和鉴定操作
密钥管理函数 C_GenerateKey 产生一个保密密钥
C_GenerateKeyPair 产生一个公共/私钥对
C_WrapKey 加密一个密钥
C_UnwrapKey 解密一个密钥
C_DeriveKey 从基础密钥派生一个密钥
随机数生成函数 C_SeedRandom 把一个附加种子材料加入随机数字生成器
C_GenerateRandom 生成随机数
并行功能管理函数 C_GetFunctionStatus 已废弃函数,返回CKR_FUNCTION_NOT_PARALLEL
C_CancelFunction 已废弃函数,返回CKR_FUNCTION_NOT_PARALLEL

 

3、CSP接口标准

CSP接口标准为微软所颁发,在windows操作系统上通行。CSP中重要的概念是容器(container)。一个容器中具有一对公私钥。而证书却是这一对密钥的附加属性了。

 

CSP总共有23个函数接口。简介如下:

接口类型 函数名称 描述
CSP连接函数 CPAcquireContext 为应用程序创建一个上下文
CPGetProvParam 返回CSP相关的信息
CPReleaseContext 释放CPAcquireContext创建的上下文
CPSetProvParam 设置CSP的参数操作
CSP密钥生成和交换函数 CPDeriveKey 从一个数据散列中生成一个会话密钥,它保证生成的密钥互不相同
CPDestroyKey 释放一个密钥句柄,释放后,句柄将无效,密钥将无法再被访问
CPExportKey 从CSP容器中导出密钥
CPGenKey 用来生成密钥或密钥对
CPGenRandom 使用随机数填充一个缓冲
CPGetKeyParam 用来得到加密操作密钥的属性
CPGetUserKey 用来获取CSP容器中的持久密钥对
CPImportKey 从一个blob中导入密钥到CSP容器中
CPSetKeyParam 设置密钥的属性
CSP加解密函数 CPDecrypt 用来解密先前被加密的数据
CPEncrypt 用来加密明文
CSP散列和数字签名函数 CPCreateHash 初始化并散列输入数据
CPDestroyHash 删除一个散列对象句柄
CPDuplicateHash 创建一个散列对象的拷贝
CPGetHashParam 获取散列对象的计算结果
CPHashData 散列输入的数据
CPSetHashParam 定制一个散列对象的属性
CPSignHash 签名一个散列对象
CPVerifySignature 校验一个数字签名

 

4、国密接口标准

国家密码管理局在2011年也制定了相关的接口标准,其标准在上层方面借鉴或参考了CSP接口,存在容器的概念,在底层操作上借鉴或参考了P11接口,有对象的标准,同时支持获取相关属性。具体国密局接口标准及其修订情况,请参考国家密码管理局网站。

值得说明的是,在国内政务等一些平台上,已经开始逐渐推广国密接口,如卫生部的医疗信息平台。因此需要研发人员关注和重视。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值