Class: Miscreant::AES::SIV

Inherits:
Object
  • Object
show all
Defined in:
lib/miscreant/aes/siv.rb

Overview

The SIV misuse resistant authenticated encryption mode

This class is intended for power users. If you’re uncertain if you should be using it, you probably want the ‘Miscreant::AEAD` API.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, mac_class = :CMAC) ⇒ SIV

Create a new AES-SIV instance

Parameters:

  • key (String)

    32-byte or 64-byte Encoding::BINARY cryptographic key

  • mac (:CMAC, :PMAC)

    (optional) MAC function to use (default CMAC)



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/miscreant/aes/siv.rb', line 26

def initialize(key, mac_class = :CMAC)
  Internals::Util.validate_bytestring("key", key, length: [32, 64])
  length = key.length / 2

  case mac_class
  when :CMAC
    @mac = CMAC.new(key[0, length])
  when :PMAC
    @mac = PMAC.new(key[0, length])
  else raise ArgumentError, "bad MAC class: #{mac_class} (expected :CMAC or :PMAC)"
  end

  @ctr = Internals::AES::CTR.new(key[length..-1])
end

Class Method Details

.generate_key(size = 32) ⇒ String

Generate a new random AES-SIV key of the given size

Parameters:

  • size (Integer) (defaults to: 32)

    size of key in bytes (32 or 64)

Returns:

  • (String)

    newly generated AES-SIV key

Raises:

  • (ArgumentError)


17
18
19
20
# File 'lib/miscreant/aes/siv.rb', line 17

def self.generate_key(size = 32)
  raise ArgumentError, "key size must be 32 or 64 bytes" unless [32, 64].include?(size)
  SecureRandom.random_bytes(size)
end

Instance Method Details

#inspectString

Inspect this AES-SIV instance

Returns:

  • (String)

    description of this instance



44
45
46
# File 'lib/miscreant/aes/siv.rb', line 44

def inspect
  to_s
end

#open(ciphertext, associated_data = []) ⇒ String

Verify and decrypt an AES-SIV ciphertext, authenticating it along with the associated data

Parameters:

  • ciphertext (String)

    an Encoding::BINARY string to decrypt

  • associated_data (Array<String>) (defaults to: [])

    optional array of message headers to authenticate

Returns:

  • (String)

    decrypted plaintext

Raises:



68
69
70
71
72
73
74
75
76
# File 'lib/miscreant/aes/siv.rb', line 68

def open(ciphertext, associated_data = [])
  raise TypeError, "expected String, got #{ciphertext.class}" unless ciphertext.is_a?(String)
  v = ciphertext[0, Internals::Block::SIZE]
  plaintext = @ctr.encrypt(_zero_iv_bits(v), ciphertext[Internals::Block::SIZE..-1])
  t = _s2v(associated_data, plaintext)
  raise IntegrityError, "ciphertext verification failure!" unless Internals::Util.ct_equal(t, v)

  plaintext
end

#seal(plaintext, associated_data = []) ⇒ String

Encrypt a message using AES-SIV, authenticating it along with the associated data

Parameters:

  • plaintext (String)

    an Encoding::BINARY string to encrypt

  • associated_data (Array<String>) (defaults to: [])

    optional array of message headers to authenticate

Returns:

  • (String)

    encrypted ciphertext

Raises:

  • (TypeError)


54
55
56
57
58
59
# File 'lib/miscreant/aes/siv.rb', line 54

def seal(plaintext, associated_data = [])
  raise TypeError, "expected String, got #{plaintext.class}" unless plaintext.is_a?(String)
  v = _s2v(associated_data, plaintext)
  ciphertext = @ctr.encrypt(_zero_iv_bits(v), plaintext)
  v + ciphertext
end