Module: DUKPT::Encryption

Included in:
Decrypter
Defined in:
lib/dukpt/encryption.rb

Constant Summary collapse

REG3_MASK =
0x1FFFFF
SHIFT_REG_MASK =
0x100000
REG8_MASK =
0xFFFFFFFFFFE00000
LS16_MASK =
0x0000000000000000FFFFFFFFFFFFFFFF
MS16_MASK =
0xFFFFFFFFFFFFFFFF0000000000000000
KEY_MASK =
0xC0C0C0C000000000C0C0C0C000000000
PEK_MASK =
0x00000000000000FF00000000000000FF
KSN_MASK =
0xFFFFFFFFFFFFFFE00000
DEK_MASK =

Used by IDTECH reader

0x0000000000FF00000000000000FF0000

Instance Method Summary collapse

Instance Method Details

#aes_decrypt(key, message) ⇒ Object



100
101
102
# File 'lib/dukpt/encryption.rb', line 100

def aes_decrypt(key, message)
  openssl_encrypt("aes-128-cbc", key, message, false)
end

#cipher_mode=(cipher_type) ⇒ Object



15
16
17
18
19
20
21
22
23
# File 'lib/dukpt/encryption.rb', line 15

def cipher_mode=(cipher_type)
  if cipher_type == "ecb"
    @cipher_type_des = "des-ecb"
    @cipher_type_tdes = "des-ede"
  else
    @cipher_type_des = "des-cbc"
    @cipher_type_tdes = "des-ede-cbc"
  end
end

#dek_from_key(key) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/dukpt/encryption.rb', line 65

def dek_from_key(key)
  key = key.to_i(16)

  key = key ^ DEK_MASK

  left = (key & MS16_MASK) >> 64
  right = (key & LS16_MASK)

  invariant_key_hex = hex_string_from_val(key, 16)

  left = triple_des_encrypt(invariant_key_hex, hex_string_from_val(left, 8))
  right = triple_des_encrypt(invariant_key_hex, hex_string_from_val(right, 8))

  left = hex_string_from_val(left.to_i(16), 8)
  right = hex_string_from_val(right.to_i(16), 8)

  [left, right].join
end

#derive_DEK(ipek, ksn) ⇒ Object



88
89
90
# File 'lib/dukpt/encryption.rb', line 88

def derive_DEK(ipek, ksn)
  dek_from_key(derive_key(ipek, ksn))
end

#derive_IPEK(bdk, ksn) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/dukpt/encryption.rb', line 92

def derive_IPEK(bdk, ksn)
	ksn_cleared_count = (ksn.to_i(16) & KSN_MASK) >> 16
	left_half_of_ipek = triple_des_encrypt(bdk, hex_string_from_val(ksn_cleared_count, 8)) 
	xor_base_derivation_key = bdk.to_i(16) ^ KEY_MASK
	right_half_of_ipek = triple_des_encrypt(hex_string_from_val(xor_base_derivation_key, 8), hex_string_from_val(ksn_cleared_count, 8))
	ipek_derived = left_half_of_ipek + right_half_of_ipek
end

#derive_key(ipek, ksn) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/dukpt/encryption.rb', line 25

def derive_key(ipek, ksn)
  ksn_current = ksn.to_i(16)
  
  # Get 8 least significant bytes
  ksn_reg = ksn_current & LS16_MASK

  # Clear the 21 counter bits
  ksn_reg = ksn_reg & REG8_MASK
  
  # Grab the 21 counter bits
  reg_3 = ksn_current & REG3_MASK
  shift_reg = SHIFT_REG_MASK
  
  #Initialize "curkey" to be the derived "ipek"
  curkey = ipek.to_i(16)
  while (shift_reg > 0)
  	if shift_reg & reg_3 > 0
  	  ksn_reg = shift_reg | ksn_reg          
      curkey = keygen(curkey, ksn_reg)
  	end
  	shift_reg = shift_reg >> 1
  end
  hex_string_from_val(curkey, 16)
end

#derive_PEK(ipek, ksn) ⇒ Object



84
85
86
# File 'lib/dukpt/encryption.rb', line 84

def derive_PEK(ipek, ksn)
  pek_from_key(derive_key(ipek, ksn))      
end

#des_encrypt(key, message) ⇒ Object



112
113
114
# File 'lib/dukpt/encryption.rb', line 112

def des_encrypt(key, message)
	openssl_encrypt(cipher_type_des, key, message, true)
end

#keygen(key, ksn) ⇒ Object



50
51
52
53
54
55
56
57
58
59
# File 'lib/dukpt/encryption.rb', line 50

def keygen(key, ksn)
  cr1 = ksn
  cr2 = encrypt_register(key, cr1)      
  
  key2 = key ^ KEY_MASK
  
  cr1 = encrypt_register(key2, cr1)

  [hex_string_from_val(cr1, 8), hex_string_from_val(cr2, 8)].join.to_i(16)      
end

#pek_from_key(key) ⇒ Object



61
62
63
# File 'lib/dukpt/encryption.rb', line 61

def pek_from_key(key)
  hex_string_from_val((key.to_i(16) ^ PEK_MASK), 16)
end

#triple_des_decrypt(key, message) ⇒ Object



104
105
106
# File 'lib/dukpt/encryption.rb', line 104

def triple_des_decrypt(key, message)
	openssl_encrypt(cipher_type_tdes, key, message, false)
end

#triple_des_encrypt(key, message) ⇒ Object



108
109
110
# File 'lib/dukpt/encryption.rb', line 108

def triple_des_encrypt(key, message)
	openssl_encrypt(cipher_type_tdes, key, message, true)
end