Class: OpenSSL::CCM

Inherits:
Object
  • Object
show all
Defined in:
lib/openssl/ccm.rb,
lib/openssl/ccm/version.rb

Overview

Abstract from http://tools.ietf.org/html/rfc3610:

Counter with CBC-MAC (CCM) is a generic authenticated encryption block cipher mode. CCM is defined for use with 128-bit block ciphers, such as the Advanced Encryption Standard (AES).

At the moment there is no update function, because length of data and additional_data are needed at the begin of cipher process. In future init(nonce, data_len, additional_data_len) could be a solution, to solve this problem. After init, update(data) could be used to set additional_data first followed by data.

Constant Summary collapse

VERSION =
'1.3.0'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cipher, key, mac_len) ⇒ Object

Creates a new CCM object.

Raises:

Parameters:

  • one of the supported algorithms like 'AES'

  • the key used for encryption and decryption

  • the length of the mac. needs to be in 4, 6, 8, 10, 12, 14, 16



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/openssl/ccm.rb', line 42

def initialize(cipher, key, mac_len)
  raise CCMError, "unsupported cipher algorithm (#{cipher})" unless CCM.ciphers.include?(cipher.upcase)
  raise CCMError, 'invalid key length' unless key.b.length >= 16
  raise CCMError, 'invalid mac length' unless (4..16).step(2).include?(mac_len)

  cipher_key_size = if key.length < 24 then '128'
                    elsif key.length < 32 then '192'
                    else '256' # rubocop:disable Lint/ElseLayout
                    end

  @cipher = OpenSSL::Cipher.new("#{cipher.upcase}-#{cipher_key_size}-CBC")
  @key = key
  @mac_len = mac_len
end

Class Method Details

.ciphers[String]

Searches for supported algorithms within OpenSSL

Returns:

  • supported algorithms



29
30
31
32
# File 'lib/openssl/ccm.rb', line 29

def self.ciphers
  selected = OpenSSL::Cipher.ciphers.select { |c| c.match(/-(128|192|256)-CBC$/i) }
  @ciphers ||= selected.map { |e| e[0..-9].upcase }.uniq
end

Instance Method Details

#decrypt(data, nonce, additional_data = '') ⇒ String

Decrypts the input data and checks the appended mac. If additional data was used for encryption, its needed for decryption, to check the authentication (mac).

Parameters:

  • the data to decrypt

  • the nonce used for decryption

  • (defaults to: '')

    additional data to check authentication (not part of the output)

Returns:

  • the decrypted data without mac



82
83
84
85
86
87
88
89
90
# File 'lib/openssl/ccm.rb', line 82

def decrypt(data, nonce, additional_data = '')
  valid?(data, nonce, additional_data)

  new_data = crypt(data.b[0...-@mac_len], nonce)
  new_mac = mac(new_data, nonce, additional_data)
  return new_data if new_mac == data.b[-@mac_len..-1]

  ''
end

#encrypt(data, nonce, additional_data = '') ⇒ String

Encrypts the input data and appends mac for authentication. If there is additional data, its included into mac calculation.

Parameters:

  • the data to encrypt

  • the nonce used for encryption

  • (defaults to: '')

    additional data to authenticate with mac (not part of the output)

Returns:

  • the encrypted data with appended mac



66
67
68
69
70
# File 'lib/openssl/ccm.rb', line 66

def encrypt(data, nonce, additional_data = '')
  valid?(data, nonce, additional_data)

  crypt(data, nonce) + mac(data, nonce, additional_data)
end