Module: Smartcard::Gp::Des

Defined in:
lib/smartcard/gp/des.rb

Overview

DES and 3DES encryption and MAC logic for GlobalPlatform secure channels.

Class Method Summary collapse

Class Method Details

.crypt(key, data, iv = nil, decrypt = false, use_ecb = false) ⇒ Object

Perform DES or 3DES encryption.

Args:

key:: the encryption key to be used (8-byte or 16-byte)
data:: the data to be encrypted or decrypted
iv:: initialization vector
decrypt:: if +false+ performs encryption, otherwise performs decryption
use_ecb:: if +false+, uses the CBC mode, otherwise uses ECB

Returns the encrypted / decrypted data.



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/smartcard/gp/des.rb', line 35

def self.crypt(key, data, iv = nil, decrypt = false, use_ecb = false)
  cipher_name = key.length == 8 ? 'DES' : 'DES-EDE'
  cipher_name += use_ecb ? '' : '-CBC'
  
  cipher = OpenSSL::Cipher::Cipher.new cipher_name
  decrypt ? cipher.decrypt : cipher.encrypt
  cipher.key = key
  cipher.iv = iv || ("\x00" * 8)
  cipher.padding = 0
  crypted = cipher.update data
  crypted += cipher.final
  crypted
end

.mac_3des(key, data, iv = nil) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/smartcard/gp/des.rb', line 61

def self.mac_3des(key, data, iv = nil)
  # Output transformation: add 80, then 00 until it's block-sized.
  data = data + "\x80"
  data += "\x00" * (8 - data.length % 8) unless data.length % 8 == 0
  
  # The MAC is the last block from 3DES-encrypting the data.
  crypt(key, data, iv)[-8, 8]
end

.mac_retail(key, data, iv = nil) ⇒ Object

Computes a MAC using DES mixed with 3DES.



50
51
52
53
54
55
56
57
58
59
# File 'lib/smartcard/gp/des.rb', line 50

def self.mac_retail(key, data, iv = nil)
  # Output transformation: add 80, then 00 until it's block-sized.
  data = data + "\x80"
  data += "\x00" * (8 - data.length % 8) unless data.length % 8 == 0

  # DES-encrypt everything except for the last block.
  iv = crypt(key[0, 8], data[0, data.length - 8], iv)[-8, 8]
  # Take the chained block and supply it to a 3DES-encryption. 
  crypt(key, data[-8, 8], iv)
end

.random_bytes(bytes) ⇒ Object

Generates random bytes for session nonces.

Args:

bytes:: how many bytes are desired

Returns a string of random bytes.



21
22
23
# File 'lib/smartcard/gp/des.rb', line 21

def self.random_bytes(bytes)
  OpenSSL::Random.random_bytes bytes
end