首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用DUKPT加密的读卡器中生成密文?

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

Stack Overflow用户
提问于 2013-06-28 18:25:44
回答 4查看 8.5K关注 0票数 8

代码语言:javascript
复制
`BDK = "0123456789ABCDEFFEDCBA9876543210"` `KSN = "FFFF9876543210E00008"` 

生成的密文如下

代码语言:javascript
复制
"C25C1D1197D31CAA87285D59A892047426D9182EC11353C051ADD6D0F072A6CB3436560B3071FC1FD11D9F7E74886742D9BEE0CFD1EA1064C213BB55278B2F12"`

我找到了here。我知道这个密文是基于BDK和KSN的,但是这个128个长度的密文是如何生成的呢?它涉及哪些步骤或用于此的算法?有人能用简单的步骤解释一下吗。我发现我在谷歌上搜索时很难理解我得到的文档。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-07-08 01:16:04

关于DUKPT,在上有一些解释。如果这还不能满足你,这里有一些简短的解释。

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

什么是DUKPT?

派生的每事务唯一密钥(DUKPT)是一种密钥管理方案。它使用一次性加密密钥,该密钥来自加密的实体(或设备)和解密数据的实体(或设备)共享的秘密主密钥。为什么选择DUKPT?任何加密算法的安全性都取决于它的密钥。如果用于通过算法加密数据的密钥不安全,则最强算法是无用的。这就像用最大最坚固的锁锁住你的门,但如果你把钥匙藏在门垫下面,锁本身就没用了。当我们谈论加密时,我们还需要记住,数据必须在另一端解密。通常,任何加密方案中最薄弱的环节都是在加密方和解密方之间共享密钥。DUKPT是一种尝试,以确保双方都可以加密和解密数据,而不必传递加密/解密密钥。VISA发布的加密最佳实践文档还建议使用DUKPT实现PCI DSS合规性。

DUKPT如何工作

DUKPT使用为每个事务生成的一次性密钥,然后将其丢弃。优点是,如果这些密钥中的一个被泄露,那么只有一个事务会被泄露。使用DUKPT,发起方(例如,Pin Entry设备或PED)和接收方(处理器、网关等)共享密钥。此密钥实际上并不用于加密。取而代之的是,使用从该主密钥派生的另一个一次性密钥来加密和解密数据。重要的是要注意,主密钥不应该从导出的一次性密钥中恢复。要解密数据,接收端必须知道使用了哪个主密钥来生成一次性密钥。这意味着接收端必须存储和跟踪每个设备的主密钥。对于支持许多设备的人来说,这可能是一项繁重的工作。需要一种更好的方法来处理这个问题。这就是它在现实生活中的工作方式:接收器有一个称为基础派生密钥(BDK)的主密钥。BDK应该是秘密的,永远不会与任何人分享。此密钥用于生成称为初始Pin加密密钥(IPEK)的密钥。由此生成一组名为Future keys的密钥,并丢弃IPEK。设备制造商将每个未来密钥嵌入到PED中,并与其共享这些密钥。这个额外的推导步骤意味着接收器不必跟踪进入PED的每个密钥。它们可以在需要时重新生成。

接收器与PED制造商共享未来密钥,PED制造商在每个PED中嵌入一个密钥。如果这些密钥中的一个被泄露,PED可以用从BDK导出的新的未来密钥来更新密钥,因为BDK仍然是安全的。

加密和解密

当数据需要从PED发送到接收器时,该设备中的Future key用于生成一次性密钥,然后将该密钥与加密算法一起使用来加密数据。然后,该数据与密钥序列号(KSN)一起被发送到接收器,密钥序列号(KSN)由设备ID和设备事务计数器组成。

然后,接收器根据KSN生成IPEK,并从中生成设备使用的Future密钥,然后生成用于加密数据的实际密钥。有了这个密钥,接收器将能够解密数据。

Source

票数 15
EN

Stack Overflow用户

发布于 2013-07-08 01:11:17

首先,让我引用你链接的完整源码,其中你只提供了3行……

代码语言:javascript
复制
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

现在你要问的是“密文”是怎么产生的.

好吧,首先我们知道它是基于“明文”的,它在代码中用来验证解密是否有效。

明文是0填充的-通过使用此DecrypterTest TestCase验证解密,它适合正在测试的加密。

让我们看一下编码代码,然后...

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

由于DecrypterTEst使用"cbc",很明显,加密使用:

代码语言:javascript
复制
 @cipher_type_des = "des-cbc"
 @cipher_type_tdes = "des-ede-cbc"

再往下一点加密代码,下面就解决了我们寻找答案的问题:

代码语言:javascript
复制
ciphertext = des_encrypt(...

这表明我们确实在查看DES加密的结果。

现在,DES的块大小为64位。这是(64/8=) 8字节二进制,或者“密文”是字节的十六进制编码文本表示- 16个字符的十六进制。

“密文”长度为128个十六进制字符,这意味着它包含(128个十六进制字符/16个十六进制chars=) 8个DES块,每个64位加密信息。

将所有这些总结为一个简单的答案:

在查看“密文”时,您看到的是(8个块) DES加密数据,它使用人类可读的十六进制(2个十六进制字符=1个字节)表示法,而不是DES加密将产生的原始二进制字节。

至于“重新创建”密文所涉及的步骤,我倾向于告诉您只需使用ruby项目的相关部分,即您提出问题的基础。只需查看源码即可。"“中的文件很好地解释了这一切,我非常确定您需要的所有功能都可以在项目的GitHub存储库中找到。或者,您可以尝试自己重新创建它-使用您选择的首选编程语言。您只需要处理两件事: DES加密/解密和bin- to -hex/hex-to-bin转换。

票数 5
EN

Stack Overflow用户

发布于 2015-06-19 17:30:31

由于这是关于这个的第一个话题,我想我应该分享一下我是如何对密文进行编码的。这是我第一次使用Ruby,特别是为了使用DUKPT

首先,我必须获取ipek和pek (与decrypt中相同)方法。然后解压明文字符串。将解压后的字符串转换为72字节的数组(同样,如果我的术语不正确,请原谅)。

我注意到在dukpt gem作者示例中,他使用了以下纯文本字符串

“%B5452300551227189^霍根/保罗^08043210000000725000000?\x00\x00”

我觉得这个字符串是不正确的,因为名称(AFAIK)后面不应该有空格。所以它应该是

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

总而言之,这是我最终使用的解决方案,它可以加密字符串,然后使用DUKPT解密它

代码语言:javascript
复制
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

结束

"%B5452300551227189^HOGAN/PAUL^08043210000000725000000?“

FFFF9876543210E00008 boomedukpt

(我的ruby gem、KSN和纯文本字符串)

2542353435323330303535313232373138395e484f47414e2f5041554c5e30383034333231303030303030303732353030303030303f000000000000000000000000000000000000

(我的ruby gem在调用hex_string_from_unpacked之后在解包的字符串上做了一个放入操作)

C25C1D1197D31CAA87285D59A892047426D9182EC11353C0B82D407291CED53DA14FB107DC0AAB9974DB6E5943735BFFE7D72062708FB389E65A38C444432A6421B7F7EDD559AF11

(我的ruby gem在加密的字符串上做了一次puts )

%B5452300551227189^HOGAN/PAUL^08043210000000725000000?

(我的ruby gem在dukpt gem上调用decrypt之后做了一次puts )

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17362567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档