当前位置: 首页 > article >正文

[翻译]ANSI X9.24-3-2017

目录

1 目的

2 范围

2.1 应用

3 参考文献

4 术语和定义

4.1 高级加密标准(AES)

4.2 AES

4.3 算法

4.4 ANSI

4.5 基础推导密钥(BDK)

4.6 BDK

4.7 BDK ID

4.8 加密密钥

4.9 加密密钥同步

4.10 密码强度

4.11 派生

4.12 派生标识符(ID)

4.13 派生密钥

4.14 每笔交易派生唯一密钥(DUKPT)

4.15 初始DUKPT密钥

4.16 初始密钥

4.17 初始密钥ID

4.18 ISO

4.19 密钥

4.20 PAN

4.21 个人识别号(PIN)

4.22 主帐号(PAN)

4.23 PIN

4.24 安全加密设备(SCD)

4.25 SCD

4.26 对称密钥

4.27 TDEA

4.28 交易发起SCD

4.29 三重数据加密算法(TDEA)

4.30 工作密钥

5 概述

5.1 密钥管理

5.2 加密密钥同步

5.3 唯一的初始密钥

6 AES DUKPT

6.1 算法描述

6.1.1 KSN 兼容模式

6.1.2 派生密钥OID

6.1.3 密钥和密钥大小

6.2 辅助函数与定义

6.2.1 枚举

6.2.2 密钥长度函数

6.3 密钥派生函数

6.3.1 算法

6.3.2 Derivation Data 派生数据

6.3.3 Create_Derivation_Data创建派生数据(本地子例程)

6.3.4 安全方面的考虑

6.4 主机安全模块算法

6.4.1 派生初始密钥

6.4.2 主机派生工作密钥

6.4.3 中间派生密钥、派生数据示例

6.4.4 工作密钥派生出数据示例

6.5 交易发起设备算法

6.5.1 算法参数

6.5.2 储存区域

6.5.3 处理程序

6.5.4 基本密码定义

7 附件:标准下载


美国金融服务国家标准 ANIS X9.24-3-2017

零售金融服务 对称秘钥管理 第3部分 每笔交易导出的唯一秘钥

批准日期:2017年10月11日

对称密钥管理第3部分:每次交易的派生唯一密钥

1 目的

        此密钥管理标准与高级加密标准(AES)一起使用(请参阅参考4),用于管理对称密钥,这些对称密钥可用于保护金融服务环境中的消息和其他敏感信息。基于AES的任何过程的安全性和可靠性直接取决于对称加密密钥的保护。

        本标准规定了从初始终端密钥生成唯一交易密钥的要求和指导方针,使得(1)终端不保留任何可以在交易完成后用于推导交易密钥的信息,(2)主机安全模块可以使用有限数量的加密操作推导出相同的交易密钥。

        该标准描述了基于 TDEA(在附录C中描述)的原始每笔交易派生唯一密钥(DUKPT)算法方法的更新,该方法基于 AES,并且具有许多其他安全改进。可以使用AES或TDEA算法生成密钥。建议使用本标准中描述的实现来执行新的 DUKPT 实现。

        参考文献2附件A中描述的原始双长度密钥TDEA DUKPT实现载于本文附件C。

2 范围

        本标准的这一部分描述了 AES DUKPT算法,该算法用于根据交易号从初始终端 DUKPT密钥中推导出密钥。推导出的密钥可用于各种功能,例如对PIN、数据或其他密钥进行加密,用于推导出其他密钥,用于消息验证等。AES DUKPT支持从AES-128、AES-192和AES-256的初始密钥中推导出 AES-128、AES-192、AES-256 以及双倍和三倍长度的 TDEA 密钥。

        其他测试向量和Python参考实现可以在http://www.x9.org上获取

2.1 应用

        本标准的这一部分适用于实施技术以保护用于身份验证、加密消息和其他敏感数据的加密密钥的机构。

        强制性标准技术和程序用“应”字表示。指南以“应该”一词表示。

3 参考文献

        下列引用文件对本文件的应用是必不可少的。对于有日期的引用文件,仅注明引用的是哪一个版本。对于未注明日期的引用文件,其最新版本(包括所有的修改)适用于本文件。

  1. ANS X9.24-1:2017, Retail Financial Services- Symmetric Key Management, Part 1: Using SymmetricTechniques (Ballot note-Anticipate publishing in 2017)

  2. ANS X9.24-1:2009, Retail Financial Services-Symmetic Key Management, Part 1: Using Symmetric2Techniques

  3. NIST SP800-67, Recommendation for the Triple Data Encryption Algorithm (TDEA) Block Cipher

  4. FIPS 197: Advanced Encryption Standard (AES), November 26, 2001

  5. FIPS 198-1: The Keyed-Hash Message Authentication Code (HMAC), July 1. 2008

The following publications are applicable and may be referenced in this part of this standard

  1. ANS X9.8-1, Personal ldentification Number (PIN) Management and Security

  2. ANS X9.24-2, Retail Financial Services Symmetric Key Management Part 2: Using Asymmetric Techniquesfor the Distribution of Symmetric Keys

  3. IS0 16609,Banking-Requirements for Message Authentication using Symmetric Techniques8.

  4. ISO 8583, Bankcard Originated Messages - interchange Message Specifications - Content for FinancialTransactions

  5. 1S0 9797-1, information technology - Security techniques - Message Authentication Codes (MACs) - Part 1.Mechanisms using a block cipher

  6. 1SO/TR 14742,Recommendations on Cryptographic Algorithms and their Use

  7. NIST SP800-38:RecommendationforBlock CipherModes ofOperation,PartB:TheCMAC Mode for Authentication(May 2005)

  8. ANS X9.102-2008, $ymmetric Key Cryptography For the Financial Services industry - Wrapping of Keys andAssociated Data

  9. ANS X9.119, Retail Financial Services - Requirements for Protection of Sensitive Payment Card Data - Par1:Using Encryption Methods

  10. 1S0 11568-2,Financial Services-Key Management (Retail)-Part 2, Symmetricciphers, their keymanagement and life cycle

  11. NIST SP 800-57:Recommendation for Key Management- Part 1: General

  12. NIST SP 800-108: Recommendation for Key Derivation using Pseudorandom Functions

  13. M. Bellare, J. Kilian, and P. Rogaway. The security of the cipher block chaining message authenticationcode. Journal of Computer and System Sciences 61(3):362-399, 2000.

4 术语和定义

4.1 高级加密标准(AES)

        参考文献4中指定的算法。

4.2 AES

        参见“高级加密标准”

4.3 算法

        有明确规定的数学运算过程;一组规则,如果遵循这些规则,将得到规定的结果

4.4 ANSI

                美国国家标准协会

4.5 基础推导密钥(BDK)

在推导过程中用于生成初始 DUKPT 密钥的密钥。主机使用相同的密钥来推导当前事务密钥。

4.6 BDK

        参见“基础推导密钥”

4.7 BDK ID

        BDK ID是一个32位值,用于标识基础推导密钥。在TDEA DUKPT规范中,此值以前称为密钥集ID(KSI))(见附件C)。

4.8 加密密钥

        一个秘密参数,用于确定加密函数的操作,例如:

  1. 从明文到密文的转换,反之亦然

  2. 同步生成密钥数据

  3. 计算或验证消息身份验证码

4.9 加密密钥同步

        对交易进行加密处理的两个节点确定相同的交易密钥的能力

4.10 密码强度

        给定密码算法和密钥大小的已知攻击的计算成本。密码强度通常是密钥大小的函数,但即使它们的密钥大小相同,不同的算法可能具有不同的密码强度。给定算法和密钥大小的强度可能因算法的使用而不同。例如,使用很少或没有明文-密文对的算法可能比使用许多对的算法更不容易受到攻击。

4.11 派生

        一种用于从另一值导出一个值的加密转换过程。在本标准的上下文中,它通常用于从另一密钥导出一个加密密钥。

4.12 派生标识符(ID)

        一个32位值,用于标识在BDK ID指定的基础推导密钥下导出的特定初始密钥。以前称为19位值Device ID(DID)或TRSM ID。

4.13 派生密钥

        一种密钥,用于使用推导过程,以加密方式计算另一密钥。

4.14 每笔交易派生唯一密钥(DUKPT)

        一种密钥管理方法,该方法为每个事务使用唯一密钥,并防止披露由事务发起设备使用的任何过去密钥。唯一的交易密钥是从基础推导密钥中派生出来的,该派生密钥仅使用作为每笔交易一部分传输的非机密数据。

4.15 初始DUKPT密钥

        加载到SCD中的唯一密钥,该密钥是从DUKPT BDK推导出的。

4.16 初始密钥

        参见“初始DUKPT密钥"

4.17 初始密钥ID

        初始密钥ID是一个64位值,用于标识在基础推导密钥下导出的特定初始密钥。它是BDK lD和派生ID的级联。

4.18 ISO

        国标准化组织

4.19 密钥

        参见“加密密钥“

4.20 PAN

        参见“主帐号”

4.21 个人识别号(PIN)

        一串数字数字,作为持卡人与发卡人之间的共享机密而建立,以便日后用于验证授权卡的使用

4.22 主帐号(PAN)

        一个分配的号码,由发卡机构标识号、个人账户标识和lSO/lEC 7812-1中规定的公司校验位组成,用于标识发卡机构和持卡人

4.23 PIN

        参见“个人识别号”

4.24 安全加密设备(SCD)

        一种提供物理和逻辑保护的加密服务和存储的设备(例如,PIN入口设备(PED)或硬件安全模块(HSM)。SCD可以集成到更大的系统中,如ATM或POS终端。

4.25 SCD

        参见“安全加密设备”

4.26 对称密钥

        在对称密码算法(例如TDEA或AES)中使用的加密密钥。用于加密的对称密钥也用于解密。

4.27 TDEA

        参见“三重数据加密算法”

4.28 交易发起SCD

        发起金融交易的原始设备(例如PIN加密设备)。处理事务的中间设备不是交易发起的SCD

4.29 三重数据加密算法(TDEA)

        参考文献3中指定的算法。

4.30 工作密钥

        AES DUKPT算法的输出密钥,用于加密操作,以加密、解密、认证或验证交易数据。

5 概述

        衍生的每笔交易统一密钥(DUKPT)算法定义了一个为每笔交易生成一个或多个唯一密钥的过程,而不要求交易发起的SCD保留任何可以确定该SCD之前使用的任何密钥的消息,也不需要确定任何其他交易发起的SCD已经或将要使用的密钥。使用基本派生密钥和交易中包含的数据元素,接收SCD将派生出发起SCD使用的密钥。

5.1 密钥管理

        接收交易的SCD(例如HSM)应从以下方面确定发起交易的SCD所使用的当前交易密钥:

  1. 交易密钥序列号中包含的非机密信息

  2. 基础推导密钥

        基础推导密钥:

  1. 用于一个或多个接收SCD(例如,在收单机构)中

  2. 不存在于任何发起交易的SCD中(例如,在销售点)

  3. 用于使用初始密钥ID(密钥序列号KSN)生成交易发起SCD的唯一初始DUKPT密钥

  4. 用于在接收SCD处生成当前交易密钥

  5. 可用于为许多原始SCD生成唯一的初始DUKPT密钥。

        基础导出密钥应按照参考文献1进行管理。

        密钥序列号应使用BDK ID。密钥序列号由三个子字段组成。

        最左边的子字段是BDK ID,用于选择适用于发起交易的SCD的基础导出密钥。

        第二个子字段是DERIVATION ID。BDK ID与DERIVATION ID连接起来,并使用所选的基本导出密钥对其进行加密,结果是在初始化时加载到发起交易的SCD中的初始DUKPT密钥(尽管可能在几年前从该SCD中擦除)。

        第三个子字段是交易计数器。发起SCD应针对每笔交易增加其交易计数器的数量。

        一旦与初始DUKPT密钥关联的交易计数器达到最大值,则发起SCD应停止使用与该初始DUKPT密钥关联的任何密钥,除非是为了计算加密新初始密钥的密钥加密密钥。接收系统(不一定是SCD)应该验证之前的交易计数器没有被重放,以提高鲁棒性并防止密钥重复使用。初始DUKPT密钥和交易计数器是密钥推导过程的输入,该过程生成用于当前交易的交易密钥。在该方法的规范(第6节)中,即使交易计数器可以有超过十亿个不同的值,转换过程也不需要超过16个推导循环。

        请注意,初始加载的密钥是基础导出密钥、BDK ID和DERIVATION ID的函数。因此,只要没有两个具有相同BDK ID的原始SCD具有相同的DERIVATION ID,则不会为任何两个原始SCD提供相同的初始DUKPT密钥。

        该方法应在接收SCD上运行,如图1所示。

图1 接收SCD的DUKPT

        发起SCD应计算并使用当前的交易密钥,以便接收SCD可以使用图1所示的过程确定该密钥。发起SCD还应在当前交易完成后立即擦除当前交易密钥的所有记录。

        图2显示了此方法如何在发起SCD上运行的示例。此SCD存储多个中间派生密钥。在新交易开始时,交易计数器(密钥序列号的最右侧部分)递增,然后用于选择这些中间验证密钥之一作为当前交易密钥。所选密钥将从未来的密钥存储中擦除。请注意,密钥序列号与当前交易一起传输。

        在交易完成时,利用交易计数器,从当前交易密钥中派生出一些中间派生密钥(有时没有,有时一个或多个)。然后这些新生成的中间派生密钥存储在由交易计数器确定的未来密钥存储中的那些位置,并擦除当前交易密钥。因此,SCD不会保留有关用于任何先前交易的任何密钥的信息。

图2-发起SCD的DUKPT

        在图1和图2中,推导过程“A”和“B”不同但相关。在发起SCD处生成、存储和选择中间派生密钥,接收SCD能够以类似的方式确定当前事务密钥。

        初始DUKPT密钥和相关密钥序列号都应加载到发起交易的SCD中。发起SCD应确保交易计数器设置为零。

5.2 加密密钥同步

        这种方法本质上是自同步的。

        不需要特殊恢复,因为同步不会丢失。

5.3 唯一的初始密钥

        使用相同基础派生密钥初始化的交易发起SCD不得使用相同的DERlVATION ID进行初始化。当相同基础派生密钥安装在多个KLD中,并且DERlVATION ID是基于计数器时,应存在一种机制来确保由每个密钥加载设备(KLD)初始化的SCD不会具有相同的初始密钥(例如,对一个或多个KLD中的每个密钥实例使用DERlVATION ID范围,或对同一密钥的每个实例使用不同的BDK ID)。

        初始密钥ID不得重复使用,即使使用相同的设备,因为这会导致重复使用相同的初始密钥。

        与 BDK ID 关联的可能的 DERlVATION ID 的数量是有限的。一旦所有 DERlVATION ID都被使用,就应使用新的BDK 或 BDK ID 进行未来的注入。如果 DERIVATION ID 是一个在每次注入时递增的计数器,则从备份中恢复应包括一种机制,以确保自上次备份以来已注入的 Key Serial Numbers 不会被重复使用。

6 AES DUKPT

        本标准的其余部分描述了 AES DUKPT,这是一种使用 AES 密钥生成每笔交易唯一密钥的现代算法。对于同一笔交易,可以推导出具有不同用途和类型的多个工作密钥。使用 AES DUKPT 推导过程推导出的每个工作密钥可以是 AES 密钥,也可以是 TDEA 密钥。

        AES DUKPT 使用AES密钥导出函数生成AES、两个密钥TDEA和三个密钥 TDEA密钥。所述技术支持所有AES密钥大小(128、192和256位)。DUKPT的主要目标是在EFT/POS环境中获取PIN加密密钥。但是,在不需要PIN的交易中,算法的使用越来越多,例如创建密钥来加密信用卡号码。因此,下面的描述不止可以派生PIN密钥; 该算法可以派生PIN加密密钥、消息身份验证密钥、数据加密密钥、密钥加密密钥和密钥派生密钥。

        AES 版本的 DUKPT与基于TDEA的 DUKPT非常相似(参见附件C)。但是,为了利用密码学技术的进步和计算机处理速度和内存大小的提高,已经进行了一些更改。AES和 TDEA DUKPT 之间的区别如下所示:

  1. 用于密钥导出的基于DEA的单向函数被基于NIST SP800-108的密钥导出函数所取代,并使用AES-ECB作为底层函数。

  2. 在AES DUKPT中,所有密钥都使用相同的密钥导出函数来导出。TDEA DUKPT使用4种不同的密钥派生技术:triple-DEA派生初始DUKPT密钥,DES-X样式单向函数用于寄存器密钥,PIN和MAC密钥的变体,以及TDEA和变体的结合派生数据加密密钥。

  3. 初始密钥 ID(IKID)为64位,而不是59位。IKID由32位 BDKID和32位DERlVATION ID(DID)组成。以前,这被称为初始密钥序列号,由40 位密钥集索引和 19 位设备 ID 组成。

  4. 交易计数器(TC)是32位而不是21位,最多允许16个1位代替10个

  5. 密钥序列号(KSN)是96位而不是80位。KSN由初始密钥ID和交易计数器组成。

  6. 该算法支持具有21或32个密钥寄存器的交易源设备

  7. 该算法包括支持在现有密钥下加载新的初始密钥

        下面的描述与对每个交易派生唯一密钥的原始描述略有不同。除了上面提到的,这两个描述基本上相同。DUKPT是一个复杂的算法,用不同的方式描述它可能有助于读者理解。

        AES DUKPT有时会被安装在最初为 TDEA DUKPT 设计的网络中。对于这些环境,格式更改通常需要最小化,因此不建议增加密钥序列号(KSN,初始密钥ID和交易计数器的连接)的大小。下面的描述包括对可以使用 TDEA DUKPT的 80 位 KSN 的 KSN 兼容模式的讨论。请注意,AES 的块大小是 DEA的两倍,因此 KSN 兼容模式不能保证与现有网络格式的兼容性。

        该标准描述了 AES DUKPT算法,并规定了交易发起设备(例如 PED 终端)和交易接收设备(例如 HSM)的功能。为确保正确生成密钥序列号和密钥,应执行以下描述的方法或其等效功能。

        在下面的任何描述中,假定位或字节的顺序是这样的,即最左边的位、十进制数字、十六进制数字或字节是最显著的,最右边的位、十进制数、十六进制数或字节是最不显著的。

6.1 算法描述

        如第5节所述,该算法的目标是为每笔交易提供一个唯一的密钥,而不会保留任何有关交易来源设备中任何先前密钥的信息。在使用密钥后,设备上不会留下任何可用于重构该密钥或先前密钥的信息。为了描述如何在派生密钥系统的上下文中实现这一点,我们将首先描述一种简化的技术,它不是实际实现的技术,但它易于理解,并且可以用于解释实际实现的技术。

        每个发起交易的设备最初都会注入一个唯一的初始密钥。设备管理很简单,因为初始密钥是从基本密钥和设备特定信息中推导出来的。在 DUKPT中,该密钥称为基本推导密钥(BDK)。因此,每个设备都会得到一个唯一的初始密钥 ID 和一个从 BDK 和初始密钥 ID 推导出来的初始密钥。

        当初始密钥被注入到发起交易的设备时,它会与初始密钥ID(BDK ID和 DerivationID 的连接)以及一个初始化为零的交易计数器一起存储。每次交易后,该计数器都会增加。每次交易计数器增加时,都会使用旧密钥对其进行加密,生成的密文成为新密钥。因此,新密钥是旧密钥的“不可逆转换”。给定新密钥,没有可行的方法可以确定旧密钥。

        在每条消息中,发起交易的设备都会发送加密字段和/或 MAC数据,以及初始密钥 ID 和交易计数器的连接。收单方能够确定初始密钥,因为它在其 SCD 中使用基本密钥,并且知道在推导过程中使用的设备特定信息。完成此操作后,收单方能够执行上述图示中所示的过程,使用计数器值(二进制)..000001,然后为计数器值..000010重复此过程,然后..000011,等等,直到消息中包含的交易计数器的值。通过上述过程多次传递的结果是用于根据需要导出PIN、数据加密或MAC密钥的当前密钥。

        上述过程虽然在理论上是可行的,但实际显然是不可行的。交易发起设备的预期寿命高达 10亿PIN 加密(在 KSN 兼容模式下为 100 万或 200万),因此,一旦交易计数达到相当高的计数,交易接收设备将需要过多的加密周期来推导出当前密钥。

        在另一端,接收交易的设备可以通过使用初始密钥对计数器进行加密来推导出每个密钥。但是,为了实现在交易发起设备中不保留任何旧密钥材料的目标,这将要求它预先计算并存储将来需要的所有密钥,这对于十亿个密钥来说是不可行的。

        需要一种“密钥转换”技术,该安全模块可以在不经过所有中间密钥的情况下进行跟踪。也就是说,该模块能够向前迈出“巨大的一步”,而无需重新生成每个中间密钥以到达当前密钥,而事务发起设备仍然可以在每个“巨大的一步”之间通过许多可能性,从而使安全存储要求不会过于繁重。

        有几种方法可以实现这一目标。这里选择的方法是使每个密钥推导(不一定是)前一个密钥的函数,而是该密钥的交易计数器包含相同的位配置,减去最右边的“1”位。换句话说:

        与交易计数器值相对应的密钥: 是一种不可逆转的钥匙转换对应于交易计数器值:

与交易计数器值相对应的密钥:                      是一种不可逆转的钥匙转换对应于交易计数器值:
0000 1011 0011                                0000 1011 0010
0000 1011 0010                                0000 1011 0000
0011 0000 1000                                0011 0000 0000
...                                           ...

        结果,许多密钥可能都是同一密钥的不可逆变换,例如,与交易计数器值相对应的密钥:

..0110 0101 0100 0001

..0110 0101 0100 0010

..0110 0101 0100 0100

..0110 0101 0100 1000

..0110 0101 0101 0000

..0110 0101 0110 0000

        所有与交易计数器值对应的密钥的不可逆变换都是:

..0110 0101 0100 0000

        上面列出的六个交易计数值中的每一个都有一个与之关联的唯一键,即使所有六个结果键都基于相同的键。为了描述如何实现这一点,我们将定义:

        K-A 作为与 ...0110 0101 0100 0000相关联的密钥。

以及:

        K-1 作为与 ...0110 0101 0100 0001 相关联的密钥

        K-2 作为与 ...0110 0101 0100 0010 相关联的密钥

        K-3 作为与 ...0110 0101 0100 0100 相关联的密钥

        K-4 作为与 ...0110 0101 0100 1000 相关联的密钥

        K-5 作为与 ...0110 0101 0101 0000 相关联的密钥

        K-6 作为与 ...0110 0101 0110 0000 相关联的密钥

然后:

        K-1 = ...0110 0101 0100 0001 在K-A下加密

        K-2 = ...0110 0101 0100 0010 在K-A下加密

        K-3 = ...0110 0101 0100 0100 在K-A下加密

        K-4 = ...0110 0101 0100 1000 在K-A 下加密

        K-5 = ...0110 0101 0101 0000 在K-A下加密

        K-6 = ...0110 0101 0110 0000 在K-A下加密

        这样,K-1到K-6是每个唯一的密钥,但每个都是同一个密钥K-A的不可逆变换。

        请注意,K-A将被使用,因此在任何密钥K-1到K-6被使用之前,它将从发起交易的设备中擦除。在 K-A被使用和擦除之前,K-1到K-6(在本例中)将被生成和存储以供将来使用。因此,发起交易的设备能够存储多个这样的中间推导密钥。发起交易的设备存储的中间推导密钥的数目等于交易计数器中的二进制位数。

        使用此方案,收单方的安全模块可以相对容易地根据其关联的交易计数器值推导出任何密钥。在首先推导出设备特有的初始密钥后,该模块只需要执行与交易计数器值中的“1”位数量大致相同的加密操作。例如,假设安全模块接收到一个加密的 PIN 块,以及一个交易计数器值为10101100 0010。(为了简化示例,使用了短于实际计数器的计数器。)假设安全模块确定初始密钥为“K-”,则安全模块随后执行以下步骤:

  1. 使用密钥K-I加密 1000 0000 0000

  2. 使用步骤a的结果加密 1010 0000 0000

  3. 使用步骤b的结果加密 1010 1000 0000

  4. 使用步骤c的结果加密 1010 1100 0000

  5. 使用步骤d的结果加密 1010 1100 0010

  6. 从步骤e的结果推导出PIN密钥

        因此,在这个示例中,安全模块仅在6个加密循环中确定了用于加密所涉PIN的PIN加密密钥。

        以前的 DUKPT 标准最多只能支持 100 万次加密,因为使用了 21位的交易计数器,计数器值中最多只能设置10个“1”比特。在许多环境中,交易发起设备在其生命周期内可能会处理超过 100万个交易。因此,AES DUKPT提供了三种增强功能,以延长设备的使用寿命:

  1. AES DUKPT包括生成称为 DUKPT 更新密钥的密钥加密密钥的选项,以便主机可以向设备发送在该密钥下加密的新初始密钥,还会发送新的初始密钥ID。

  2. AES DUKPT包括使用最多16个“1”位的交易计数器,而不是只使用10个或更少“1”位的交易计数器的选择。

  3. AES DUKPT将交易计数器的大小增加到32位,最大为16位“1”值。

        一旦设备开始使用这些设置之一生成事务密钥,它应继续使用相同的设置,直到加载新密钥为止。

6.1.1 KSN 兼容模式

        该标准定义了 KSN 的新格式,该格式比传统的TDEA KSN长16位。如果网络基础设施和现有软件无法轻松容纳较长的值,但设计人员仍希望利用新版本提供的增强的加密强度,则本节定义了与网络兼容的80位 KSN。请注意,它不是加密兼容的;它使用 AES 进行密钥推导,因此即使使用相同的 KSN,也不会推导出相同的密钥。

        回顾一下,新的96位KSN具有以下结构:

初始密钥ID(64位)

交易计数器(32位)

        旧版 KSN 的结构如下:

旧版初始密钥ID(59位)

交易计数器(21位)

        对于KSN兼容模式,当终端处理KSN并获取HSM时,KSN将具有以下内部格式:

填充(4位) 旧版初始密钥ID(59位) 填充(1位)

填充(11位) 交易计数器(21位)

        所有填充位都为二进制零。

        注意,填充将59位旧版初始密钥ID转换为64位初始密匙ID,并将21位旧版交易计数器转换为32位交易计数器。

        计数器中1位的最大数是10还是16取决于实现。

        注意,终端将在内部处理过程中包括填充位,但将在传输过程中剥离它们。同样,接收端HSM将在导出初始密钥之前将它们添加回来。

        对于接收端来说,没有完全明确的方法来区分AES 80位KSN和TDEA。因此,接收端必须根据初始密钥 ID 标识的 BDK算法进行确定,并将此信息提供给 HSM。

        在必要或有用的情况下,建议保留以字节“OE”开头的旧版初始密钥ID,以便在KSN兼容模式下使用。

        例子:

        密钥集ID = 0E11111111

        设备ID = 22222

        初始密钥ID = 0E1111111122222

        旧版KSN = 0E111111112222200000

        内部KSN = 00E111111112222200000000

6.1.2 派生密钥OID

        在交易消息的某个地方,包含有关用于加密交易的密钥类型和长度(AES-128、AES-256、3-key TDEA等)的信息可能是有用的。建议使用以下保留对象标识符(OID):

          1.3.133.16.840.9.24.1.1-AES-128

          1.3.133.16.840.9.24.1.2-AES-192

          1.3.133.16.840.9.24.1.3-AES-256

          1.3.133.16.840.9.24.1.4-2-key TDEA

          1.3.133.16.840.9.24.1.5-3-key TDEA

        相关 OID(ROIDS)可用于节省交易消息中的空间。使用这些 OID 表明交易密钥具有给定的算法和大小,并且是根据本标准的规范导出的。

6.1.3 密钥和密钥大小

        派生函数用于从终端初始密钥推导出中间派生密钥,这些中间派生密钥用于为交易生成工作密钥。工作密钥应与其推导出的密钥具有相同或更弱的强度。

表1 按BDK大小的AES DUKPT允许工作密钥

派生工作密钥

AES-128 BDK

AES-192 BDK

AES-256 BDK

2TDEA 工作密钥

允许

允许

允许

3TDEA 工作密钥

允许

允许

允许

AES-128 工作密钥

允许

允许

允许

AES-192 工作密钥

不允许

允许

允许

AES-256 工作密钥

不允许

不允许

允许

HMAC-128 工作密钥

允许

允许

允许

HMAC-192 工作密钥

不允许

允许

允许

HMAC-256 工作密钥

不允许

不允许

允许

        对于HMAC密钥,只要哈希长度适当,这个标准对作为HMAC一部分使用的哈希函数没有要求。

6.2 辅助函数与定义

6.2.1 枚举

        以下枚举定义了AES DUKPT函数伪码中使用的一些数据类型。

// DerivationPurpose identifies if this derivation is to create an initial key
// or any other key type to help select which derivation data table to use
enum DerivationPurpose
{
    _Initial_Key_,
    _Derivation_or_Working_Key_
}

// KeyUsage defines the possible key usages that can be derived
enum KeyUsage
{
    _Key_Encryption_Key_,
    _PIN_Encryption_,
    _Message_Authentication_generation_,
    _Message_Authentication_verification_,
    _Message_Authentication_both_ways_,
    _Data_Encryption_encrypt_.
    _Data_Encryption_decrypt_,
    _Data_Encryption_both_ways_,
    _Key_Derivation_,
    _Key_Derivation_Initial_Key_
}

// KeyType defines the cryptographic key type being derived
enum KeyType
{
    _2TDEA_,
    _3TDEA_,
    _AES128_,
    _AES192_,
    _AES256_
}

6.2.2 密钥长度函数

        辅助密钥长度函数Key_Length,用于将密钥类型转换为密钥长度(以bit为单位)。

Key_Length(keyType)
{
    if(keyType == _2TDEA_)
        return 128;
    else if(keyType == _3TDEA_)
        return 192;
    else if(keyType == _AES128_)
        return 128;
    else if(keyType == _AE192_)
        return 192;
    else if(keyType == _AES256_)
        return 256;
}

6.3 密钥派生函数

6.3.1 算法

        第6.2节将DUKPT密钥派生过程描述为计数器的加密,以帮助简化对该概念的理解。事实上,AES DUKPT采用NIST 800-108 KDF(参考文献17),在计数器模式下以AES-ECB作为底层函数来派生密钥,等效于使用AES-CMAC用于派生输出块大小倍数的密钥。此功能如图3所示。

        下列值是此函数的输入。

  • Derivation Data 派生数据

    • 用于派生密钥的非机密数据。这是加密的数据。下节将对这些数据进行定义。

  • Derivation Key 派生密钥

    • 在派生函数中用作密钥的秘密值。对于此应用,派生密钥是加密派生数据的AES密钥。派生密钥可以是以前调用派生函数的结果。

  • Derivation Key 派生密钥长度

    • 派生密钥的长度。

  • L,输出密钥长度

    • 输出密钥(正在创建的密钥)的长度(以bit为单位)。此值为128、192或256。

          输出为AES或 TDEA 密钥。

          "导出密钥"(本地子程序)

          Derive_Key函数接受派生密钥、要导出的密钥的所需输出长度和派生数据(在下节中定义),并输出一个与导出密钥长度相同的导出密钥。

Derive_Key(derivationKey,keyType,derivationData)
{
    L = Key_Length(keyType);
    n= ceil(L/128);//number of blocks required to construct the derived key
    for (i=l;i<=n;i++){
        // Set the value of the derivation data key block counter field equal to
        // the block count being derived.
        // First block is 0x01,second block is 0x02.
        derivationData[1]=i;
        result[(i-1)*16..i*16-1] = AES_Encrypt_ECB(derivationKey, derivationData);
    }
    derivedKey=result[0..(L/8)-1];
    return derivedKey;
}

6.3.2 Derivation Data 派生数据

        Derive_Key函数使用Derivation Data,用于派生出特定类型的密钥。下表列出了 16字节的Derivation Data 派生数据,这些数据适合上述密钥派生算法中使用的 AES 加密算法的一个数据块。

        表2显示了交易发起设备创建初始密钥的派生数据。表3用于生成所有其他密钥。这两个表之间的主要区别在于最后8个字节。对于用于创建初始密钥的派生数据的表A-1,最后8个字节使用完整的初始密钥 ID,需要提供唯一的初始密钥。对于推导所有其他密钥的表A-2,使用初始密钥 ID(Derivation ID)的最右侧 4个字节加上交易计数器的 4个字节。

表2 终端密钥派生数据

Byte #

Field Name

Description

Encoding

Range of Values

0

Version

Version lD of this table structure. This edition is represented as version 1 represented by 0x01

2H

0x01

1

Key Block Counter

A counter that is incremented for each 16-byte block of keying material generated for a pair of encryption and MAC keys. Starts at 1 for each key being generated

2H

0x01-0x02

2-3

Key Usage Indicator

Indicates how the key to be derived is to beused. The initial terminal key is always a key derivation key.

4H

0x8001 =Key Derivation, Initial key

4-5

Algorithm Indicator

Indicates the encipherment algorithm that is going to use the derived key

4H

0x0002 = AES 128 bit

0x0003 = AES 192 bit

0x0004 = AES 256 bit

6-7

Length

Length, in bits, of the keying material being

generated.

4H

0x0080 if 128 bits is being generated (AES-128)

0x00C0 if 192 bits is being generated (AES-192)

0x0100 if 256 bits is being generated (AES-256)

8-15

Initial Key lD

The terminal's Initial Key lD, the left most 64bits of the Key Serial Number

16H

0x0000000000000000

to

0xFFFFFFFFFFFFFFFF

表3 其他密钥派生数据

Byte #

Field Name

Description

Encoding

Range of Values

0

Version

Version lD of this table structure. This edition is represented as version 1 represented by 0x01

2H

0x01

1

Key Block Counter

A counter that is incremented for each 16-byte block of keying material generated for a pair of encryption and MAC keys. Starts at 1 for each key being generated

2H

0x01-0x02

2-3

Key Usage Indicator

Indicates how the key to be derived is to beused.

4H

0x0002 = Key Encryption Key

0x1000 = PIN Encryption

0x2000 = Message Authentication,generation

0x2001= Message Authentication,verification

0x2002 = Message Authentication, bothways

0x3000= Data Encryption, encrypt

0x3001 =Data Encryption, decrypt

0x3002 = Data Encryption, bothways

0x8000 = Key Derivation

4-5

Algorithm Indicator

Indicates the encipherment algorithm that is going to use the derived key

4H

0x0000 = 2-key TDEA

0x0001 = 3-key TDEA

0x0002 = AES 128 bit

0x0003 = AES 192 bit

0x0004 = AES 256 bit

0x0005 = HMAC

6-7

Length

Length, in bits, of the keying material being

generated.

4H

0x0080 if 128 bits is being generated (AES-128, 2TDEA, or 128-bit HMAC key)

0x00C0 if 192 bits is being generated (AES-192, 3TDEA, or 192-bit HMAC key)

0x0100 if 256 bits is being generated (AES-256 or 256-bit HMAC key)

8-11

Initial Key lD

The rightmost half of the terminal's Initial Key ID.

8H

0x00000000

to

OxFFFFFFFF

12-15

Transaction Counter

The 32-bit transaction counter

8H

0x00000000

to

OxFFFFFFFF

6.3.3 Create_Derivation_Data创建派生数据(本地子例程)

        Create_Derivation_Data函数根据Table 2和Table 3创建派生数据,具体取决于派生目的。输入参数有keyUsage、derivedKeyType、initialKeyID和transaction counter。

Create_Derivation_Data(derivationPurpose,keyUsage, derivedKeyType, initialKeyID,counter)
{
    //Set Version ID of the table structure.
    DerivationData[0] = 0x01: //version 1
    //set Key Block Counter
    DerivationData[1] = 0x01; //1 for first block,2 for second, etc.
    //set Key Usage Indicator
    if(keyUsage == _Key_Encryption_Key_)
        DerivationData[2..3] = 0x0002;
    else if(keyUsage == _PIN_Encryption_)
        DerivationData[2..3] = 0x1000;
    else if(keyUsage == _Message_Authentication_generation_)
        DerivationData[2..3] = 0x2000;
    else if(keyUsage == _Message_Authentication_verification_)
        DerivationData[2..3] = 0x2001;
    else if(keyUsage == _Message_Authentication_both_ways_)
        DerivationData[2..3] = 0x2002;
    else if(keyUsage == _Data_Encryption_encrypt_)
        DerivationData[2..3] = 0x3000;
    else if(keyUsage == _Data_Encryption_decrypt_)
        DerivationData[2..3 = 0x3001;
    else if(keyUsage == _Data_Encryption_both_ways_)
        DerivationData[2..3] = 0x3002;
    else if(keyUsage == _Key_Derivation_)
        DerivationData[2..3] = 0x8000;
    else if(keyUsage == _Key_Derivation_Initial_Key_)
        DerivationData[2..3] = 0x8001;
        
    //set Algorithm Indicator and key size
    //Note:2TDEA and 3TDEA are includedas an option for working keysand must not be used for initial keys or derivation keys
    if(derivedKeyType == _2TDEA_)     
        DerivationData[4..5] = 0x0000;
    else if(derivedKeyType == _3TDEA_)
        DerivationData[4..5] = 0x0001;
    else if(derivedKeyType == _AES128_)
        DerivationData[4..5】= 0x0002;
    else if(derivedKeyType == _AES192_)
        DerivationData[4..5] = 0x0003;
    else if(derivedKeyType == _AES256_)
        DerivationData[4..5] = 0x0004;
        
    //set length of key material being generated
    //Note:2TDEA and 3TEA are includedas an option for working keys and must not be used for initial keys or derivation keys
    if(derivedKeyType == _2TDEA_)
        DerivationData[6..7] = 0x0080:
    else if(derivedKeyType == _3TDEA_)
        DerivationData[6..7] = 0x00C0;
    else if(derivedKeyType == _AES128_)
        DerivationData[6..7] = 0x0080:
    else if(derivedKeyType == _AES192_)
        DerivationData[6..7] = 0x00C0;
    else if(derivedKeyType == _AES256_)
        DerivationData[6..7] = 0x0100;

    //next 8 bytes depend on the derivation purpose
    if (derivationPurpose == _Initial_Key_)
        DerivationData[8..15] = initialKeyID[0..7];
    else if(derivationPurpose == _Derivation_or_Working_Key_)
    {
        DerivationData[8..11]  = initialKeyID[4..7];
        DerivationData[12..15] = counter[0..3];
    }
    return DerivationData;    
}

6.3.4 安全方面的考虑

        NIST SP800-108 密钥派生函数需要使用伪随机函数,并批准使用CMAC工作模式的块密码来提供此功能。在本标准中,我们建议使用 AES ECB 模式,而不是使用 AES CMAC,尽管 AES ECB 未被 NIST批准用于此用途。

        这种选择的理由是性能。对于大多数应用程序,密钥的派生相对不频繁,一旦创建,派生的密钥将可以用于一些操作。在 DUKPT中,服务器必须使用迭代过程派生工作密钥,最多调用 18次密钥派生函数来处理单个 PIN 块。单个主机可能与数万个输入设备通信,每个设备仅发送一两个块的报文。因此,密钥派生函数的处理成本对系统性能至关重要。对于AES 128 密钥,使用CMAC而不是EBC将削减密钥派生函数大约一半的性能。

        尽管 AES ECB 具有性能优势,但它并未被 NIST 密钥派生函数所认可,因为 NIST 函数需要处理各种密钥派生应用,具有不同长度和类型的密钥派生数据。在 DUKPT 中,我们将派生数据限制为单个块。这种单个块的限制使我们能够安全地使用 ECB。以下回答了有关在此功能中使用 ECB 而不是CMAC的一些常见问题。

  • ECB是伪随机置换而不是伪随机函数吗?

    • 当与单个数据块派生一起使用时,ECB和CMAC都是伪随机置换,NIST对基于CMAC的派生没有限制。此外,为了区分伪随机函数和伪随机置换,密钥需要被重复使用约$$2^{64}$$次,这在当前网络上只有非常多可探测的攻击时发生。

  • CMAC不是比EBC更安全吗?

    • 根据参考文献18,当数据长度固定为单个块长度时,ECB和MAC是一样安全的。在数据的最后一个块上添加 CMAC的白化步骤,仅仅是为了提高使用任意长度数据的安全性。对于DUKPT,我们不允许使用随意长度的数据。

  • CMAC不阻止对密钥派生函数的已知明文攻击吗?

    • 由于密钥派生函数的输出是一个密钥,而且该密钥从未公开,因此这两种方法都非常难以进行已知明文攻击。如果工作密钥被不恰当地泄露,CMAC可能会使此类攻击更加困难。然而,目前还没有针对 AES 的明显已知明文攻击。如果有这样的攻击被发现,它对 PIN 块加密的影响将是深远的。保护 DUKPT 免受这种理论攻击不会显著提高整体网络的安全性。

  • CMAC是否使穷举搜索变得更加困难?

    • 同样,攻击者首先需要破解(或通过穷举搜索恢复)工作密钥。从工作密钥开始,对派生密钥的穷举搜索,对于CMAC和 ECB是非常相似。对于 ECB,攻击者只需选择密钥并尝试将派生数据作为单个 ECB 操作进行加密。对于CMAC,攻击者选择密钥并计算派生数据的CMAC。CMAC需要调用两次 AES 块操作,因此需要大约两倍的时间来恢复密钥。

  • DUKPT从非常密切相关的推导数据中推导出大量密钥。那些理论上相关的密钥可用于加密相同的数据或密切相关的数据。这里是否有相关密钥攻击,CMAC可以缓解吗?

    • 已知的相关密钥攻击中不存在以这种方式相关的密钥。基本上,这意味着对两个相关明文的加密需要在密文中产生某种关系,这似乎意味着对AES 的其他类型的攻击。如果这种类型的攻击确实存在,CMAC不会完全阻止攻击,因为PIN 密钥、多个方向的数据密钥、MAC密钥等仍然是相关密钥,即使 CMAC 白色掩盖了推导树中的一些相关密钥。

6.4 主机安全模块算法

        在主机端实现 AES DUKPT 相对简单。请注意,主机不需要知道终端跳过哪些交易计数器值进行处理交易,它只需根据发送的交易计数器值计算适当的密钥。此外,主机唯一需要知道终端中寄存器数量是在发送新的初始密钥时。密钥加密密钥总是从终端支持的最高交易计数器值中派生出来,这是终端尚未使用过的交易计数器值。

        对于 KSN 兼容模式,主机只需将 80 位的 KSN 拆分为 56 位的初始密钥 ID 和 21 位的交易计数器。初始密钥 ID 用零填充到右侧,以创建 64 位。交易计数器用零填充到左侧,以创建 32 位。

6.4.1 派生初始密钥

        Derive_Initial_Key函数使用初始密钥ID 和适用于所用 AES大小的常量,根据表2设置初始密钥派生数据。

        示例#1:对于 AES128,初始密钥ID=0123456789ABCDEF,根据表2构造初始密匙的派生数据如下:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Initial Key ID

01

01

8001

0002

0080

01234567890ABCDEF

        所得到的初始密钥派生数据 = 01018001000200800123456789ABCDEF。

        此派生数据将用AES-128 BDK加密,结果将是此初始密钥ID的AES128位初始密匙。

        示例 #2:对于 AES256,初始密钥ID=FFEEDDCCBBAA9988,根据表2构造初始密匙的派生数据如下

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Initial Key ID

01

01

8001

0004

0100

FFEEDDCCBBAA9988

01

02

8001

0004

0100

FFEEDDCCBBAA9988

        所得到的派生数据是:

        第1块派生数据 = 0101800100040100FFEEDDCCBBAA9988

        第2块派生数据 = 0102800100040100FFEEDDCCBBAA9988

        每个块的派生数据都将用 AES-256 BDK加密,其结果将是两个 128 位数据块,它们被连接起来作为此初始密钥 ID 的 AES256 位初始密钥。

Derive_Initial_Key(BDK,keyType,initialKeyID)
{
    derivationData = Create_Derivation_Data(_Initial_Key_,_Key_Derivation_Initial_Key_,keyType,initialKeyID,0);
    initialKey  = Derive_Key(BDK,keyType,derivationData);
    return initialKey;
 }

6.4.2 主机派生工作密钥

        Host_Derive_Working_Key函数,使用initialKeyID和deriveKeyType (_AES128_, _AES192_, _AES256_, _2DEA_ 或 _3DEA_)从Base Derivation Key(BDK)计算初始密钥。通过当前交易计数器值从初始密钥计算出的当前派生密钥。最后,根据当前派生密钥计算工作密钥。

Host_Derive_Working_Key(BDK, deriveKeyType, workingKeyUsage, workingKeyType, initialKeyIDtransactionCounter)
{
    initialKey= Derive_Initial_Key(BDK, deriveKeyType, initialKeyID);
    
    //set the most significant bit to one and all other bits to zero
    mask = 0x80000000;
    workingCounter = 0;
    derivationKey  = initialKey;
    
    //calculate current derivation key from initial key
    while (mask>0)
    {
        if((mask AND transactionCounter)!0)
        {
            workingCounter = workingCounter OR mask;
            derivationData = Create_Derivation_Data(_Derivation_or_Working_Key_,
                                                    _Key_Derivation_,
                                                    deriveKeyType,initialKeyID,
                                                    workingCounter);
            derivationKey  = Derive_Key(derivationKey,deriveKeyType,derivationData);
        }
        mask=mask>>1;
    }
     
    // derive working key from current derivation key
    derivationData = Create_Derivation_Data(_Derivation_or_Working_Key_, workingKeyUsage,
                                           workingKeyType,initialKeyID,
                                           transactionCounter);
    workingKey  = Derive_Key(derivationKey,workingKeyType,derivationData);
    
    return workingKey;
}

6.4.3 中间派生密钥、派生数据示例

        一个派生数据用于推导中间派生密钥的示例,根据表3设置初始派生数据,并构造派生数据如下:

        示例 #1: 对于初始密钥ID=0123456789ABCDEF的AES128,计数器值为0x00000001的中间派生密钥的派生数据构造如下:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Right half of Initial Key ID

Transaction Counter

01

01

8000

0002

0080

89ABCDEF

00000001

        得到的派生数据=010180000002008089ABCDEF00000001

        此派生数据将用初始密钥加密,结果将是计数器值0x00000001的AES 128位中间派生密钥。

        示例 #2:对于 AES 256,初始密钥ID=FFEEDDCCBBAA9988,计数值为0x00000001,使用的两个 128 位块的派生数据,用于创建AES 256位中间派生密钥,如下所示:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Right half of Initial Key ID

Transaction Counter

01

01

8000

0004

0100

BBAA9988

00000001

01

02

8000

0004

0100

BBAA9988

00000001

        所得到的派生数据是:

        第1块派生数据 = 0101800000040100BBAA998800000001

        第2块派生数据 = 0102800000040100BBAA998800000001

        每个块的派生数据将使用初始密钥进行加密,结果将是两个128位数据块,它们被连接起来,使用计数值0x0000001,创建AES 256位中间派生密钥。

        示例 #3:每次派生数据计算都会更新这个派生数据,在这个AES128的例子中,如果工作计数器是0x00001200,那么派生数据的构造如下:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Right half of Initial Key ID

Transaction Counter

01

01

8000

0002

0080

89ABCDEF

00001200

        得到的派生数据 = 010180000002008089ABCDEF00001200

        这个派生数据将使用中间派生密钥对计数值为0x00001000进行加密,其中结果为计数值为0x00001200的AES 128位中间派生密钥。使用计数值为0x00001000的中间派生密钥来派生此密钥的原因是,它是计数值为0x00001200的中间派生密钥的父密钥。这是通过将0x00001200的最右边的1位进行掩码计算得出的,结果为0x00001000。

6.4.4 工作密钥派生出数据示例

        对于从当前派生密钥集派生工作密钥的示例,根据表3,构造派生数据:

        示例 #1: 数据加密,加密密钥,AES128,初始密钥ID=0123456789ABCDEF,交易计数器=0x00002345,派生数据构造如下:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Right half of Initial Key ID

Transaction Counter

01

01

3000

0002

0080

89ABCDEF

00002345

        得到的推导数据 = 010130000002008089ABCDEF00002345

        此派生数据将使用中间派生密钥对计数值为0x00002345进行加密,其中结果为AES 128位在计数器值为0x00002345的数据加密的加密密钥。

        示例 #2:同一个设备,PIN加密密钥,2-key TDEA,初始密钥ID=0123456789ABCDEF,交易计数器=0x00002345,派生数据构造如下:

Version

Key Block Counter

Key Usage Indicator

Algorithm Indicator

Length

Right half of Initial Key ID

Transaction Counter

01

01

1000

0000

0080

89ABCDEF

00002345

        得到的推导数据 = 010110000000008089ABCDEF00002345

        此派生数据将使用中间派生密钥对计数值为0x00002345进行加密,其中结果为2-key TDEA在计数器值为0x00002345的PIN加密密钥。

6.5 交易发起设备算法

6.5.1 算法参数

  • KEYLENGTH 密钥长度

    • 此值是初始密钥的长度。存储在寄存器中的所有中间派生密钥都将与初始密钥的长度相同。PIN、MAC或数据加密密钥可以有不同的密钥长度。

  • NUM_REG 注册数

    • 此值是中间派生密钥寄存器的数目。在3DES DUKPT中,此值总是21。在AES DUKPT中,使用32个寄存器。在使用KSN兼容模式时,AES DUKPT 此值为21。

  • MAX_WORK 最大操作数

    • 这是主机安全模块允许当前交易计数器值密钥所需的最大操作数。该值由交易计数器中的1的数量确定。在 TDEA DUKPT中,该值始终为10。对于AES DUKPT,MAX WORK值为16。AES DUKPT 在使用 KSN 兼容模式时该值为10。

6.5.2 储存区域

        自“Load Initial Key”命令发出之时起,在设备使用期内,交易发起设备将维护以下存储区域。

  • Initial Key Identifier 初始密钥标识符(ID)(64位)

    • 在伪代码中定义为全局变量 InitialKeyID,在不要求 KSN 兼容性的系统中,此值为 64 位。在具有 KSN 兼容模式的设备中,在“Load Initial Key”命令期间注入交易发起设备的寄存器是初始密钥序列号的最左侧64位。请注意,这 64 位包括来自交易计数器的位,但由于计数器值为零,因此此方法有效地在右侧用零填充59 位的 InitialKeyID。在设备使用期间,该寄存器的内容保持固定,直到收到另一个“Load Initial Key”命令,或直到收到“更新初始密匙”命令。

  • Transaction Counter 交易计数器(32位)

    • 在伪代码中定义为全局变量TransactionCounter。此变量定义了自初始密钥首次加载以来发生的交易数量的计数器。由于某些计数器值(如下解释)会被跳过,因此该值并不总是代表已执行的实际交易数目。

    • 附注:交易计数器的极大值由中间派生密钥寄存器的数目决定。当NUM_REG=32时,交易计数器的极大值是0xFFFF0000。当NUM_REG=21时,交易计数器的极大值是0x001FF800。DUKPT更新密钥的交易计数器值为0xFFFFFFFF。

  • NUM_REG(32或21)

    • 这是中间派生密钥寄存器的数目。它是32,除非在KSN兼容模式下是21

  • Intermediate Derivation Key Registers 中间派生密钥寄存器

    • 在伪代码中定义为全局数组 IntermediateDerivationKeyRegister。IntermediateDerivationKeyRegister是一组用于存储中间派生密钥的寄存器。 AES DUKPT定义了 32 个寄存器。在 KSN兼容模式下运行时,将有 21个寄存器

  • Intermediate Derivation Key In Use 正在使用的中间派生密钥

    • 在伪代码中定义为 IntermediateDerivationKeyInUse数组。IntermediateDerivationKeyInUse 是一个布尔值集合,用于存储相应的IntermediateDerivationKeyRegister 是否具有有效值。

        下列与密钥管理有关的储存区域是临时需要的:

  • Current Derivation Key 当前派生密钥(0..31)

    • 在伪代码中定义为全局变量 curentDerivationKey,其中包含 Intermediate Derivation Key Registers 的索引,该索引的内容在当前加密操作中使用。

  • Shift Register 移位寄存器(32位)

    • 在伪代码中定义为全局变量ShiftRegister。这是一个32位寄存器。该寄存器通常包含31个“0”位和一个“1”位。该寄存器用于选择一个中间派生密钥寄存器。其值为1<<CurrentDerivationKey。

  • Key Type Injected 注入的密钥类型(KeyType)

    • 这是注入的初始密钥的密钥类型,可以是 _AES128_、 _AES192_或 _AES256_。

6.5.3 处理程序

        与TDEA DUKPT定义的原始流程不同,该标准将算法的描述限制在密钥管理功能上。PIN处理和输入被视为可能使用DUKPT密钥管理的单独系统。从这一点来看,实现 AES DUKPT 的设备需要支持三个密钥管理功能,用于其他设备使用。这些功能分别是Load_InitialKey、Generate_Working_Keys和 Update_Initial_Key。每个功能要执行的步骤如下所示。本节还包含这些函数常用的子函数的定义。

        备注:密钥派生函数Derive_Key在上面6.3.1节中已经定义。

  • Load Initial Key 加载初始密钥 (密钥管理命令)

    • Load_InitialKey函数输入初始密钥、初始密钥ID和初始密钥类型,来初始化系统。初始密钥类型必须是_AES128_、_AES192_ 或 _AES256_ 之一,并定义要使用的派生密钥的类型(也称为“中间派生密钥”)。

Load_Initial_Key(initialKey, initialKeyType, initialKeyID)
{
    IntermediateDerivationKeyRegister[0] = initialKey;
    IntermediateDerivationKeyInUse[0]    = true;
    CurrentDerivationKey = 0;
    InitialKeyID   = minitialKeyID;
    Transactioncounter   = 0;
    ShiftRegister  = 1;
    InitialKeyType = initialKeyType;
    
    Update_Derivation_Keys(NUM REG-1);
    
    TransactionCounter++;
}
  • Calculate DUKPT Update Key 计算DUKPT更新密钥 (可选本地子例程)

    Calculate_DUKPT_Update_Key()
    {
        bit = 1<< (NUM REG-1);
        register = NUM_REG - 1
        while((TransactionCounter & bit) == 1)
        {
            bit = bit >> 1;
            register--'
        }
        ctr = TransactionCounter & ~(bit-1);
        key = IntermediateDerivationKeyRegister[register];
        
        while (bit >0)
        {
            ctr = ctr | bit;
            derivationData = Create_Derivation_data(_Derivation_or_Working_Key_,_Key_Derivation_,
                                                    InitialKeyType,InitialKeyID,ctr)
            key = Derive_Key(key,deriveKeyType, derivationData);
            register--;
            bit = bit >> 1;
        }
        derivationData = Create_Derivation_Data(_Derivation_or_Working_Key_,
                                                _Key_Encryption_Key_,
                                                InitialKeyType,InitialKeyID,ctr);
        return Derive_Key(key,InitialKeyType,derivationData);
    }

  • Update Initial Key 更新初始密钥 (可选密钥管理命令)

        Update_Initial_Key函数生成新的加密的初始密钥,该密钥由设备上的当前初始密钥派生出的最后一个可能的密钥加密密钥进行封装,使用密钥加密密钥解密新的加密的初始密钥,并安装新加密密钥。加载新初始密钥后,交易计数器应重新设置为0。

      新初始密钥应以符合本标准要求的方式加以保护。

      解封应以符合第7.4节要求的方式实现(例如使用TR-31密钥块)

      封装密钥只能使用单一密钥封装算法和模式。

      为了实现互操作性,一旦添加了对封装AES密钥的支持,就应该使用TR-31进行交换

      如果使用TR-31密钥块,则携带初始密钥的TR-31密钥块应具有以下格式:

D nnnn B1 A X 00 N 01 00 IK 14 hhhhhhhhhhhhhhhh

          其中nnnn是十进制密钥块长度(包括计数和头),hhhhhhhhhhhhhhhh是密钥ID。

Update_Initial_Key(encryptedInitialKey,newInitialKeyType, newInitialKeyID)
{
    // derive a key encryption key from the last counter value
    // for the device
    dukptUpdateKey = Calculate_DUKPT_Update Key();
    if(!UnwrapKey(encryptedInitialKey,dukptUpdateKey,newInitialKey))
        return ERROR;
        
    Load_Initial_Key(newInitialKey, newInitialKeyType, newInitialKeyID);
    
    return SUCCESS;
}
  • Generate Working Keys 生成工作密钥 (密钥管理命令)

    • Generate_Working_Keys函数为当前交易生成工作密钥。

    • 工作密钥只能用于单一的算法和模式,且只能用于单个目的。

Generate_Working_Keys(workingKeyUsage, workingKeyType)
{
    //initialize the ShiftRegister and CurrentDerivationKey
    Set_Shift_Register();

    //advance transaction counter until current key is valid
    while (!IntermediateDerivationKeyInUse[CurrentDerivationKey])
    {
        TransactionCounter = ransactionCounter + ShiftRegister; // skip over invalid key
        if(TransactionCounter >= ((1<<NUMREG)-1))
        {
            Cease_Operation();  //this function will cease using this this key set
            return ERROR;
        }
        Set_shift_Register();
    }
    // derive a working key from the current key pointer
    derivationData = Create_Derivation_Data(_Derivation_or_Working_Key_, workingKeyUsage,
                                            workingKeyType,InitialKeyID,TransactionCounter);
    workingKey  = Derive_Key(IntermediateDerivationKeyRegister[CurrentDerivationKey],
                             workingKeyType,derivationData);
    
    Update_State_for_next_Transaction();
    
    return workingKey;
}
  • Update State for next Transaction 更新状态为下一次交易作准备(本地子例程)

    • Update_State_for_next_Transaction 函数使名为IntermediateDerivationKeyRegister的寄存器中的当前密钥及其标志无效,并递增TransactionCounter。InitialKeyType 是注入的初始密钥的密钥类型。

Count_one_Bits(value)
{
    // For clarity,a simple,straightforward implementation has been chosen.
    // There are faster ways of computing the value on most platforms.
    bits = 0;
    mask = 1 << (NUMREG-1);
    while(mask > 0)
    {
        if((value & mask)>0)
            bits = bits + 1;
        mask = mask >> 1;
    }
    return bits;
}

Update_State_for_next_Transaction()
{
    oneBits = Count_One_Bits(TransactionCounter);
    if (oneBits <= MAX WORK)
    {
        Update_Derivation_Keys(CurrentDerivationKey);
        // erase the current intermediate derivation key
        IntermediateDerivationKeyRegister[CurrentDerivationKey] = 0;
        // invalidate the current register
        IntermediateDerivationKeyInUse[CurrentDerivationKey] = false;
        // increment the transaction counter
        TransactionCounter++;
    }
    else
    { 
        // number of "one" bits in the transaction counter is greater than MAX WORK
        // erase the current intermediate derivation key
        IntermediateDerivationKeyRegister[CurrentDerivationKey] = 0;
        // invalidate the current register
        IntermediateDerivationKeyInUse[CurrentDerivationKey] = false;
        // skip transaction counter values with more than MAX WORK bits
        TransactionCounter = TransactionCounter + ShiftRegister;
    }
    // check if transaction counter has exceeded max value
    if(TransactionCounter >= ((1<<NUMREG) - 1))
    {
        Cease_Operation();// this function will cease using this this key set
        return ERROR;
    }
    return SUCCESS;
}
  • Update Derivation Keys 更新派生密钥 (本地子例程)

    • Update_Derivation_Keys函数根据 ShiftRegister、TranactionCounter、CurrentDerivationKey、 InitialKeyType 和 InitialKeylD 的当前值,更新中间派生密钥寄存器。

    • 第一次调用此函数时,star= NUM_REG - 1,所有寄存器都被初始化。

    • 在生成交易密钥后调用时,start = CurrentDerivationKey。

Update_Derivation_Keys(start)
{
    index = start;
    registerBit = 1 << start;
    baseKey= IntermediateDerivationKeyRegister[CurrentDerivationKey];
    while (registerBit != 0)
    {
        derivationData = Create_Derivation_Data(_Derivation_or_Working_Key_,
                                                _Key_Derivation_,
                                                InitialKeyType,InitialKeyID,
                                                (registerBit OR TransactionCounter));
                                                
        IntermediateDerivationKeyRegister[index] = Derive_Key(baseKey,
                                                              deriveKeyType,derivationData);
        IntermediateDerivationKeyInUse[index] =true;
        reqisterBit = registerBit >> 1:
        index = index -1;
    }
    return SUCCESS;
}
  • Set Shift Register 设置轮换寄存器(本地子程序)

    • Set_shift_Register 函数将 shiftRegister 中与TransactionCounter 中最右边的“1”位相对应的位设置为“1”,其他所有位都设置为“0”。

    • 如果 TransactionCounter = 0000 0000 0000 0010 1100 1101 1100 0011,

      • 则 shiftRegister = 0000 0000 0000 0000 0000 0000 0000 0001;

    • 如果 TransactionCounter = 0000 0000 0000 0010 1100 1101 1100 0000,

      • 则 shiftRegister = 0000 0000 0000 0000 0000 0000 0100 0000.

Set_shift_Register()
{
    ShiftRegister = 1;
    CurrentDerivationKey = 0;
    
    if(TransactionCounter == 0)
        return SUCCESS;
        
    While((ShiftRegister AND TransactionCounter)==0)
    {
        ShiftRegister = ShiftReqister << 1;
        CurrentDerivationKey++;
    }
    return SUCCESS;
 }

6.5.4 基本密码定义

        本标准中描述的所有密码使用块密码的模式运行,这意味着算法调用某些底层块密码,并将安全性建立在底层密码的安全性之上。为了本规范的目的,AES DUKPT采用高级加密标准(AES)。有关该算法定义的参考资料可以在ASC X9 SD-34中找到。

        在下面的算法描述中,以下常数用于指定AES算法的块大小:

AES_BYTES = 16

        在函数描述中使用以下AES操作。这些函数假定AES使用的是128、192或256位密钥。

AES_EncryPt_ECB(K,Y)   //给定密钥K和16字节值Y,返回AES-ECB加密的X(16字节数组)

AES_Decrypt_ECB(K,Y)  //给定密钥K和16字节值Y,返回AES-ECB解密的X(16字节数组)

7 附件:标准下载

        ANSI X9.24-3-2017


http://www.kler.cn/a/388477.html

相关文章:

  • 【Select 语法全解密】.NET开源ORM框架 SqlSugar 系列
  • whisper.cpp: PC端测试 -- 电脑端部署音频大模型
  • 【数据库原理】数据增删改查,DML、单表查询、多表连接查询
  • 鸿蒙开发:了解帧动画
  • StarRocks一次复杂查询引起的Planner超时异常
  • golangci-lint安装与Goland集成
  • AI 刷题实践选题:精选真题功能的深度剖析与学习实践| 豆包MarsCode AI刷题
  • “双十一”电商狂欢进行时,在AI的加持下看网易云信IM、RTC如何助力商家!
  • UE5.4 PCG 执行后生成函数
  • Word大珩助手:超大数字怎么读?35位数字?69位数字?
  • 嵌入式学习-网络高级-Day01
  • 【青牛科技】应用方案 | D75xx-150mA三端稳压器
  • 如何在 HFSS 3D 布局中创建 cutout 子设计
  • goroutine 介绍
  • 我爸瘫痪,我们三兄弟每月出2500让嫂子伺候,得知我工资10000,嫂子打电话:你多给1000行吗?...
  • lua脚本调用 c/c++中的接口
  • Spring Shell——快速构建终端应用,自定义终端命令
  • Maven的依赖管理、传递、冲突、父子工程的继承和聚合
  • 题目讲解15 合并两个排序的链表
  • 易语言加载dll模拟windows鼠标轨迹移动
  • 对于大根堆的计算时间复杂度的过程
  • 【模板】如何实现链表元素的反转
  • ClickHouse创建分布式表
  • 用Java实现samza转换成flink
  • linprog函数在octave中的使用
  • WPF中ImageBrush和Image的区别