简体   繁体   English

如何使用DUKPT加密在读卡器中生成密文?

[英]How ciphertext was generated in card reader using DUKPT encryption?

For 对于

`BDK = "0123456789ABCDEFFEDCBA9876543210"` `KSN = "FFFF9876543210E00008"` 

The ciphertext generated was below 生成的密文如下

"C25C1D1197D31CAA87285D59A892047426D9182EC11353C051ADD6D0F072A6CB3436560B3071FC1FD11D9F7E74886742D9BEE0CFD1EA1064C213BB55278B2F12"`

which I found here . 我在这里找到 I know this cipher-text is based on BDK and KSN but how this 128 length cipher text was generated? 我知道这个密文是基于BDK和KSN但是如何生成这个128长度的密文? What are steps involved in it or algorithm used for this? 它涉及的步骤或用于此的算法是什么? Could someone explain in simple steps. 有人可以通过简单的步骤解释。 I found it hard to understand the documents I got while googled. 我发现很难理解我用google搜索时得到的文件。

Regarding DUKPT , there are some explanations given on Wiki . 关于DUKPT ,在Wiki上有一些解释。 If that doesn't suffice you, here goes some brief explanation. 如果这还不够,这里有一些简短的解释。

Quoting http://www.maravis.com/library/derived-unique-key-per-transaction-dukpt/ 引用http://www.maravis.com/library/derived-unique-key-per-transaction-dukpt/

What is DUKPT? 什么是DUKPT?

Derived Unique Key Per Transaction (DUKPT) is a key management scheme. 每个事务的派生唯一密钥(DUKPT)是密钥管理方案。 It uses one time encryption keys that are derived from a secret master key that is shared by the entity (or device) that encrypts and the entity (or device) that decrypts the data. 它使用一次加密密钥,该密钥是从加密的实体(或设备)共享的秘密主密钥和解密数据的实体(或设备)共享的。 Why DUKPT? 为何选择DUKPT? Any encryption algorithm is only as secure as its keys. 任何加密算法都只能与其密钥一样安全。 The strongest algorithm is useless if the keys used to encrypt the data with the algorithm are not secure. 如果用于使用算法加密数据的密钥不安全,则最强的算法是无用的。 This is like locking your door with the biggest and strongest lock, but if you hid the key under the doormat, the lock itself is useless. 这就像用最大和最强的锁来锁门,但是如果你把钥匙藏在门垫下面,锁本身就没用了。 When we talk about encryption, we also need to keep in mind that the data has to be decrypted at the other end. 当我们谈论加密时,我们还需要记住,数据必须在另一端解密。 Typically, the weakest link in any encryption scheme is the sharing of the keys between the encrypting and decrypting parties. 通常,任何加密方案中最薄弱的环节是加密和解密方之间的密钥共享。 DUKPT is an attempt to ensure that both the parties can encrypt and decrypt data without having to pass the encryption/decryption keys around. DUKPT试图确保双方都可以加密和解密数据,而无需传递加密/解密密钥。 The Cryptographic Best Practices document that VISA has published also recommends the use of DUKPT for PCI DSS compliance. VISA发布的“加密最佳实践”文档还建议使用DUKPT以符合PCI DSS。

How DUKPT Works DUKPT如何运作

DUKPT uses one time keys that are generated for every transaction and then discarded. DUKPT使用为每个事务生成的一个时间密钥,然后丢弃。 The advantage is that if one of these keys is compromised, only one transaction will be compromised. 优点是,如果其中一个密钥被泄露,则只有一个事务会受到损害。 With DUKPT, the originating (say, a Pin Entry Device or PED) and the receiving (processor, gateway, etc) parties share a key. 使用DUKPT,始发(例如,引脚输入设备或PED)和接收(处理器,网关等)各方共享密钥。 This key is not actually used for encryption. 此密钥实际上不用于加密。 Instead, another one time key that is derived from this master key is used for encrypting and decrypting the data. 相反,从该主密钥导出的另一个一次性密钥用于加密和解密数据。 It is important to note that the master key should not be recoverable from the derived one time key. 请务必注意,主密钥不应从派生的一次性密钥中恢复。 To decrypt data, the receiving end has to know which master key was used to generate the one time key. 为了解密数据,接收端必须知道使用哪个主密钥来生成一次性密钥。 This means that the receiving end has to store and keep track of a master key for each device. 这意味着接收端必须存储和跟踪每个设备的主密钥。 This can be a lot of work for someone that supports a lot of devices. 对于支持大量设备的人来说,这可能是很多工作。 A better way is required to deal with this. 处理这个问题需要更好的方法。 This is how it works in real-life: The receiver has a master key called the Base Derivation Key (BDK). 这就是它在现实生活中的工作方式:接收器有一个称为Base Derivation Key(BDK)的主密钥。 The BDK is supposed to be secret and will never be shared with anyone. BDK应该是秘密的,永远不会与任何人共享。 This key is used to generate keys called the Initial Pin Encryption Key (IPEK). 该密钥用于生成称为初始引脚加密密钥(IPEK)的密钥。 From this a set of keys called Future Keys is generated and the IPEK discarded. 由此生成一组名为Future Keys的密钥,并丢弃IPEK。 Each of the Future keys is embedded into a PED by the device manufacturer, with whom these are shared. 每个Future密钥都由设备制造商嵌入到PED中,与之共享这些密钥。 This additional derivation step means that the receiver does not have to keep track of each and every key that goes into the PEDs. 这个额外的推导步骤意味着接收器不必跟踪进入PED的每个键。 They can be re-generated when required. 它们可以在需要时重新生成。

在此输入图像描述

The receiver shares the Future keys with the PED manufacturer, who embeds one key into each PED. 接收方与PED制造商共享Future密钥,PED制造商将一个密钥嵌入到每个PED中。 If one of these keys is compromised, the PED can be rekeyed with a new Future key that is derived from the BDK, since the BDK is still safe. 如果其中一个密钥被泄露,则可以使用从BDK派生的新Future密钥重新生成PED,因为BDK仍然是安全的。

Encryption and Decryption 加密和解密

When data needs to be sent from the PED to the receiver, the Future key within that device is used to generate a one time key and then this key is used with an encryption algorithm to encrypt the data. 当需要将数据从PED发送到接收器时,该设备中的Future键用于生成一次性密钥,然后该密钥与加密算法一起用于加密数据。 This data is then sent to the receiver along with the Key Serial Number (KSN) which consists of the Device ID and the device transaction counter. 然后将该数据与密钥序列号(KSN)一起发送到接收器,密钥序列号由设备ID和设备事务计数器组成。 在此输入图像描述

Based on the KSN, the receiver then generates the IPEK and from that generates the Future Key that was used by the device and then the actual key that was used to encrypt the data. 基于KSN,接收器然后生成IPEK,并从中生成设备使用的Future Key,然后生成用于加密数据的实际密钥。 With this key, the receiver will be able to decrypt the data. 使用此密钥,接收器将能够解密数据。

Source

First, let me quote the complete sourcecode you linked and of which you provided only 3 lines... 首先,让我引用您链接的完整源代码,并且您只提供了3行代码...

require 'bundler/setup'
require 'test/unit'
require 'dukpt'

class DUKPT::DecrypterTest < Test::Unit::TestCase

      def test_decrypt_track_data
        bdk = "0123456789ABCDEFFEDCBA9876543210"
        ksn = "FFFF9876543210E00008"
        ciphertext = "C25C1D1197D31CAA87285D59A892047426D9182EC11353C051ADD6D0F072A6CB3436560B3071FC1FD11D9F7E74886742D9BEE0CFD1EA1064C213BB55278B2F12"
        plaintext = "%B5452300551227189^HOGAN/PAUL ^08043210000000725000000?\x00\x00\x00\x00"

        decrypter = DUKPT::Decrypter.new(bdk, "cbc")
        assert_equal plaintext, decrypter.decrypt(ciphertext, ksn)
      end
end

Now, you're asking is how the "ciphertext" was created... 现在,你问的是“密文”是如何创建的......

Well, first thing we know is that it is based on "plaintext", which is used in the code to verify if decryption works. 嗯,首先我们知道它是基于“明文”,它在代码中用于验证解密是否有效。

The plaintext is 0-padded - which fits the encryption that is being tested by verifying decryption with this DecrypterTest TestCase. 明文是0填充的 - 它适合通过使用此DecrypterTest TestCase验证解密而正在测试的加密。

Let's look at the encoding code then... 我们来看看编码代码......

I found the related encryption code at https://github.com/Shopify/dukpt/blob/master/lib/dukpt/encryption.rb . 我在https://github.com/Shopify/dukpt/blob/master/lib/dukpt/encryption.rb找到了相关的加密代码。

As the DecrypterTEst uses "cbc", it becomes apparent that the encrypting uses: 由于DecrypterTEst使用“cbc”,很明显加密使用:

 @cipher_type_des = "des-cbc"
 @cipher_type_tdes = "des-ede-cbc"

A bit more down that encryption code, the following solves our quest for an answer: 这个加密代码稍微低一点,以下解决了我们对答案的追求:

ciphertext = des_encrypt(...

Which shows we're indeed looking at the result of a DES encryption. 这表明我们确实在看DES加密的结果。

Now, DES has a block size of 64 bits. 现在,DES的块大小为64位。 That's (64/8=) 8 bytes binary, or - as the "ciphertext" is a hex-encoded text representation of the bytes - 16 chars hex. 那是(64/8 =)8字节二进制,或 - 因为“密文”是字节的十六进制编码文本表示 - 16个字符十六进制。

The "ciphertext" is 128 hex chars long, which means it holds (128 hex chars/16 hex chars=) 8 DES blocks with each 64 bits of encrypted information. “密文”是128个十六进制字符长,这意味着它保存(128个十六进制字符/ 16个十六进制字符=)8个DES块,每个64位加密信息。

Wrapping all this up in a simple answer: 在一个简单的答案中包装所有这些:

When looking at "ciphertext" , you are looking at (8 blocks of) DES encrypted data, which is being represented using a human-readable, hexadecimal (2 hex chars = 1 byte) notation instead of the original binary bytes that DES encryption would produce. 当查看“密文”时 ,您正在查看(8个块)DES加密数据,这些数据使用人类可读的十六进制(2个十六进制字符= 1个字节)表示法来表示,而不是DES加密将使用的原始二进制字节。生产。

As for the steps involved in "recreating" the ciphertext, I tend to tell you to simply use the relevant parts of the ruby project where you based your question upon. 至于“重新创建”密文所涉及的步骤,我倾向于告诉您只需使用ruby项目中您基于问题的相关部分。 Simply have to look at the sourcecode. 只需要看一下源代码。 The file at " https://github.com/Shopify/dukpt/blob/master/lib/dukpt/encryption.rb " pretty much explains it all and I'm pretty sure all functionality you need can be found at the project's GitHub repository. https://github.com/Shopify/dukpt/blob/master/lib/dukpt/encryption.rb ”中的文件几乎解释了这一切,我非常确定您需要的所有功能都可以在项目的GitHub中找到库。 Alternatively, you can try to recreate it yourself - using the preferred programming language of your choice. 或者,您可以尝试自己重新创建它 - 使用您选择的首选编程语言。 You only need to handle 2 things: DES encryption/decryption and bin-to-hex/hex-to-bin translation. 您只需要处理两件事:DES加密/解密和bin-to-hex / hex-to-bin转换。

Since this is one of the first topics that come up regarding this I figured I'd share how I was able to encode the ciphertext. 由于这是关于此问题的第一个主题之一,我想我会分享我如何编码密文。 This is the first time I've worked with Ruby and it was specifically to work with DUKPT 这是我第一次使用Ruby,它专门与DUKPT合作

First I had to get the ipek and pek (same as in the decrypt) method. 首先,我必须获得ipek和pek(与解密相同)方法。 Then unpack the plaintext string. 然后解压缩明文字符串。 Convert the unpacked string to a 72 byte array (again, forgive me if my terminology is incorrect). 将解压缩的字符串转换为72字节数组(如果我的术语不正确,请再次原谅我)。

I noticed in the dukpt gem author example he used the following plain text string 我注意到在dukpt gem作者示例中他使用了以下纯文本字符串

"%B5452300551227189^HOGAN/PAUL ^08043210000000725000000?\\x00\\x00\\x00\\x00" “%B5452300551227189 ^ HOGAN / PAUL ^ 08043210000000725000000?\\ x00 \\ x00 \\ x00 \\ x00”

I feel this string is incorrect as there shouldn't be a space after the name (AFAIK).. so it should be 我觉得这个字符串不正确,因为名字后面不应该有空格(AFAIK)..所以它应该是

"%B5452300551227189^HOGAN/PAUL^08043210000000725000000?\\x00\\x00\\x00\\x00" “%^ B5452300551227189 HOGAN / PAUL ^ 08043210000000725000000?\\ X00 \\ X00 \\ X00 \\ X00”

All in all, this is the solution I ended up on that can encrypt a string and then decrypt it using DUKPT 总而言之,这是我最终可以加密字符串然后使用DUKPT解密它的解决方案

class Encrypt
include DUKPT::Encryption
attr_reader :bdk

def initialize(bdk, mode=nil)
  @bdk = bdk
  self.cipher_mode = mode.nil? ? 'cbc' : mode
end

def encrypt(plaintext, ksn)
  ipek = derive_IPEK(bdk, ksn)
  pek = derive_PEK(ipek, ksn)
  message =  plaintext.unpack("H*").first
  message = hex_string_from_unpacked(message, 72)
  encrypted_cryptogram = triple_des_encrypt(pek,message).upcase
  encrypted_cryptogram
end
def hex_string_from_unpacked val, bytes
  val.ljust(bytes * 2, "0")
end

end 结束

boomedukpt FFFF9876543210E00008 "%B5452300551227189^HOGAN/PAUL^08043210000000725000000?" boomedukpt FFFF9876543210E00008“%B5452300551227189 ^ HOGAN / PAUL ^ 08043210000000725000000?”

(my ruby gem, the KSN and the plain text string) (我的ruby gem,KSN和纯文本字符串)

2542353435323330303535313232373138395e484f47414e2f5041554c5e30383034333231303030303030303732353030303030303f000000000000000000000000000000000000 2542353435323330303535313232373138395e484f47414e2f5041554c5e30383034333231303030303030303732353030303030303f000000000000000000000000000000000000

(my ruby gem doing a puts on the unpacked string after calling hex_string_from_unpacked) (我的ruby gem在调用hex_string_from_unpacked后执行unpacked字符串)

C25C1D1197D31CAA87285D59A892047426D9182EC11353C0B82D407291CED53DA14FB107DC0AAB9974DB6E5943735BFFE7D72062708FB389E65A38C444432A6421B7F7EDD559AF11 C25C1D1197D31CAA87285D59A892047426D9182EC11353C0B82D407291CED53DA14FB107DC0AAB9974DB6E5943735BFFE7D72062708FB389E65A38C444432A6421B7F7EDD559AF11

(my ruby gem doing a puts on the encrypted string) (我的ruby gem做了加密字符串)

%B5452300551227189^HOGAN/PAUL^08043210000000725000000? %B5452300551227189 ^ HOGAN / PAUL ^ 08043210000000725000000?

(my ruby gem doing a puts after calling decrypt on the dukpt gem) (我的ruby gem在dukpt gem上调用解密后执行put)

看看这个: https//github.com/sgbj/Dukpt.NET ,我遇到了类似的情况,我想知道如何在终端有自己的函数调用时在终端上实现dukpt,这需要INIT和KSN来创建第一个键,所以我唯一的问题是确保INIT键在终端上以与上面提到的repo代码相同的方式生成,这很简单,使用ossl加密库为3des和ebc并应用适当的掩码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM