Class: Salsa20

Inherits:
Object
  • Object
show all
Defined in:
lib/salsa20.rb,
ext/salsa20_ext/salsa20_ext.c

Overview

Salsa20 stream cipher engine. Initialize the engine with key and iv, and then call Salsa20#encrypt or Salsa20#decrypt (they are actually identical – that’s how stream ciphers work).

Example:

encryptor = Salsa20.new(key_str, iv_str)
cipher_text = encryptor.encrypt(plain_text)

Defined Under Namespace

Classes: EngineClosedError, IllegalSeekError, InvalidKeyError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, iv) ⇒ Salsa20

Create a new Salsa20 encryption/decryption engine.

key is the encryption key and must be exactly 128-bits (16 bytes) or 256-bits (32 bytes) long

iv is the encryption IV and must be exactly 64-bits (8 bytes) long

If key or iv lengths are invalid then a Salsa20::InvalidKeyError exception is raised.

Raises:

  • (TypeError)


41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/salsa20.rb', line 41

def initialize(key, iv)
  # do all the possible checks here to make sure the C extension code gets clean variables
  raise TypeError, "key must be a String" unless key.is_a? String
  raise TypeError, "iv must be a String" unless iv.is_a? String

  raise InvalidKeyError, "key length must be 16 or 32 bytes" unless key.size == 16 || key.size == 32
  raise InvalidKeyError, "iv length must be 8 bytes" unless iv.size == 8

  @key = key
  @iv = iv
  @closed = false
  init_context # Implemented in the C extension
end

Instance Attribute Details

#ivObject (readonly)

The encryption IV (Initialization Vector) / nonce



30
31
32
# File 'lib/salsa20.rb', line 30

def iv
  @iv
end

#keyObject (readonly)

The encryption key



27
28
29
# File 'lib/salsa20.rb', line 27

def key
  @key
end

Instance Method Details

#closed?Boolean

Returns true if the last encryption was of a non 64-bytes boundry chunk. This means this instance cannot be further used (subsequent calls to Salsa20#encrypt or Salsa20#decrypt will raise a Salsa20::EngineClosedError exception); false if the instance can be further used to encrypt/decrypt additional chunks.

Returns:

  • (Boolean)


60
61
62
# File 'lib/salsa20.rb', line 60

def closed?
  @closed
end

#encrypt(input) ⇒ Object Also known as: decrypt

Encrypts/decrypts the string input. If input length is on 64-bytes boundry, you may call encrypt (or decrypt) again; once you call it with a non 64-bytes boundry chunk this must be the final chunk (subsequent calls will raise a Salsa20::EngineClosedError exception).

Returns the encrypted/decrypted string, which has the same size as the input string.

Raises:

  • (TypeError)


71
72
73
74
75
76
# File 'lib/salsa20.rb', line 71

def encrypt(input)
  raise TypeError, "input must be a string" unless input.is_a? String
  raise EngineClosedError, "instance is closed" if closed?
  @closed = true if (input.size % 64) != 0
  encrypt_or_decrypt(input) # Implemented in the C extension
end

#positionObject

Returns the current cipher stream position in bytes



92
93
94
# File 'lib/salsa20.rb', line 92

def position
  get_cipher_position * 64
end

#seek(position) ⇒ Object

Advance the cipher engine into position (given in bytes). This can be used to start decrypting from the middle of a file, for example.

Note: position must be on a 64-bytes boundry (otherwise a Salsa20::IllegalSeekError exception is raised).

Raises:



85
86
87
88
89
# File 'lib/salsa20.rb', line 85

def seek(position)
  raise IllegalSeekError, "seek position must be on 64-bytes boundry" unless position % 64 == 0
  position /= 64
  set_cipher_position(low_32bits(position), high_32bits(position)) # Implemented in the C extension
end