Class: Mcrypt

Inherits:
Object
  • Object
show all
Defined in:
lib/mcrypt.rb,
ext/mcrypt_wrapper.c

Defined Under Namespace

Classes: InvalidAlgorithmOrModeError, InvalidIVError, InvalidKeyError, PaddingError, RuntimeError

Constant Summary collapse

LIBMCRYPT_VERSION =
rb_str_new2(LIBMCRYPT_VERSION)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#new(algorithm, mode, key = nil, iv = nil, padding = nil) ⇒ Object

Creates and initializes a new Mcrypt object with the specified algorithm and mode. key, iv and padding will also be initialized if they are present.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'ext/mcrypt_wrapper.c', line 88

static VALUE mc_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE algo, mode, key, iv, padding;
    char *s_algo, *s_mode;
    MCRYPT *box;

    rb_scan_args(argc, argv, "23", &algo, &mode, &key, &iv, &padding);

    Data_Get_Struct(self, MCRYPT, box);

    /* sanity check.  should be empty still */
    if (*box != NULL)
        rb_raise(rb_eFatal, "mcrypt binding internal error");

    /* convert :rijndael_256 to "rijndael-256" */
    algo = canonicalize_algorithm(algo);
    mode = to_s(mode);

    /* mcrypt needs null-terminated strings */
    s_algo = dup_rbstring(algo, 1);
    s_mode = dup_rbstring(mode, 1);

    *box = mcrypt_module_open(s_algo, NULL, s_mode, NULL);
    if (*box == MCRYPT_FAILED) {
        char message[256];
        /* MCRYPT_FAILED is currently 0, but we should explicitly set
           to zero in case they change that. We don't want to attempt to
           free it later. */
        *box = 0;
        snprintf(message, sizeof(message),
                 "Could not initialize using algorithm '%s' with mode "
                 "'%s'.  Check mcrypt(3) for supported combinations.",
                 s_algo, s_mode);
        free(s_algo);
        free(s_mode);
        rb_raise(cInvalidAlgorithmOrModeError, message, NULL);
    }
    free(s_algo);
    free(s_mode);

    rb_iv_set(self, "@algorithm", algo);
    rb_iv_set(self, "@mode", mode);

    /* post-initialization stuff that's easier done in ruby */
    rb_funcall(self, rb_intern("after_init"), 3, key, iv, padding);

    return self;
}

Class Method Details

.algorithm_info(algorithm_name) ⇒ Object

:call-seq:

Mcrypt.algorithm_info(algorithm_name) -> Hash

Provides information about the specified algorithm. Returns a hash with the following keys:

:block_algorithm

true if the algorithm operates in blocks (mutually exclusive with stream_algorithm)

:stream_algorithm

true if the algorithm operates in bytes (mutually exclusive with block_algorithm)

:block_size

the size of blocks the algorithm works with (in bytes)

:key_size

the maximum key size this algorithm will accept (in bytes)

:key_sizes

an array containing all the key sizes the algorithm will accept (in bytes)



46
47
48
49
50
51
52
53
54
55
# File 'lib/mcrypt.rb', line 46

def algorithm_info(algorithm_name)
  {
    :block_algorithm   => block_algorithm?(algorithm_name),
    :stream_algorithm  => stream_algorithm?(algorithm_name),
    :block_size        => block_size(algorithm_name),
    :key_size          => key_size(algorithm_name),
    :key_sizes         => key_sizes(algorithm_name),
    :algorithm_version => algorithm_version(algorithm_name)
  }
end

.algorithm_version(algorithm) ⇒ Fixnum

Returns the implementation version number of the specified algorithm.

Returns:

  • (Fixnum)


475
476
477
478
479
# File 'ext/mcrypt_wrapper.c', line 475

static VALUE mck_algorithm_version(VALUE self, VALUE algo)
{
    algo = canonicalize_algorithm(algo);
    return INT2FIX(mcrypt_module_algorithm_version(RSTRING_PTR(algo), NULL));
}

.algorithmsArray

Returns an array of all the supported algorithm names.

Returns:

  • (Array)


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'ext/mcrypt_wrapper.c', line 356

static VALUE mck_algorithms(VALUE self)
{
    VALUE rv;
    int size, i;
    char **list;

    list = mcrypt_list_algorithms(NULL, &size);
    rv = rb_ary_new2(size);
    for (i = 0; i < size; i++) {
        rb_ary_push(rv, rb_str_new2(list[i]));
    }
    mcrypt_free_p(list, size);

    return rv;
}

.block_algorithm?(algorithm) ⇒ Boolean

Returns true if the specified algorithm operates in blocks.

Returns:

  • (Boolean)


400
401
402
403
404
# File 'ext/mcrypt_wrapper.c', line 400

static VALUE mck_is_block_algorithm(VALUE self, VALUE algo)
{
    algo = canonicalize_algorithm(algo);
    return TO_RB_BOOL(mcrypt_module_is_block_algorithm(RSTRING_PTR(algo),NULL));
}

.block_algorithm_mode?(mode) ⇒ Boolean

Returns true if the specified mode is for use with block algorithms.

Returns:

  • (Boolean)


451
452
453
454
455
# File 'ext/mcrypt_wrapper.c', line 451

static VALUE mck_is_block_algorithm_mode(VALUE self, VALUE mode)
{
    mode = to_s(mode);
    return TO_RB_BOOL(mcrypt_module_is_block_algorithm_mode(RSTRING_PTR(mode),NULL));
}

.block_mode?(mode) ⇒ Boolean

Returns true if the specified mode operates in blocks.

Returns:

  • (Boolean)


463
464
465
466
467
# File 'ext/mcrypt_wrapper.c', line 463

static VALUE mck_is_block_mode(VALUE self, VALUE mode)
{
    mode = to_s(mode);
    return TO_RB_BOOL(mcrypt_module_is_block_mode(RSTRING_PTR(mode),NULL));
}

.block_size(algorithm) ⇒ Fixnum

Returns the block size of the specified algorithm.

Returns:

  • (Fixnum)


424
425
426
427
428
# File 'ext/mcrypt_wrapper.c', line 424

static VALUE mck_block_size(VALUE self, VALUE algo)
{
    algo = canonicalize_algorithm(algo);
    return INT2FIX(mcrypt_module_get_algo_block_size(RSTRING_PTR(algo),NULL));
}

.canonicalize_algorithm(algo) ⇒ Object

:call-seq:

Mcrypt.canonicalize_algorithm(algorithm) -> String

Converts :rijndael_256 to “rijndael-256”. No need to call manually – it’s called for you when needed.



110
111
112
# File 'lib/mcrypt.rb', line 110

def canonicalize_algorithm(algo) #:nodoc:
  algo.to_s.downcase.gsub(/_/,'-')
end

.key_size(algorithm) ⇒ Fixnum

Returns the maximum key size of the specified algorithm.

Returns:

  • (Fixnum)


412
413
414
415
416
# File 'ext/mcrypt_wrapper.c', line 412

static VALUE mck_key_size(VALUE self, VALUE algo)
{
    algo = canonicalize_algorithm(algo);
    return INT2FIX(mcrypt_module_get_algo_key_size(RSTRING_PTR(algo),NULL));
}

.key_sizes(algorithm) ⇒ Array

Returns the key sizes supported by the specified algorithm.

Returns:

  • (Array)


436
437
438
439
440
441
442
443
# File 'ext/mcrypt_wrapper.c', line 436

static VALUE mck_key_sizes(VALUE self, VALUE algo)
{
    int *sizes, num_of_sizes, max;
    algo = canonicalize_algorithm(algo);
    max = mcrypt_module_get_algo_key_size(RSTRING_PTR(algo), NULL);
    sizes = mcrypt_module_get_algo_supported_key_sizes(RSTRING_PTR(algo), NULL, &num_of_sizes);
    return enumerate_key_sizes(sizes, num_of_sizes, max);
}

.mode_info(mode_name) ⇒ Object

:call-seq:

Mcrypt.mode_info(mode_name) -> Hash

Provides information about the specified operation mode. Returns a hash with the following keys:

:block_mode

true if the mode operates in blocks (mutually exclusive with stream_mode)

:stream_mode

true if the mode operates in bytes (mutually exclusive with block_mode)

:block_algorithm_mode

true if the mode is for use with block algorithms (mutually exclusive with stream_algorithm_mode)

:stream_algorithm_mode

true if the mode is for use with stream algorithms (mutually exclusive with block_algorithm_mode)

:mode_version

an integer identifying the version of the mode implementation



77
78
79
80
81
82
83
84
85
# File 'lib/mcrypt.rb', line 77

def mode_info(mode_name)
  {
    :block_mode            => block_mode?(mode_name),
    :stream_mode           => stream_mode?(mode_name),
    :block_algorithm_mode  => block_algorithm_mode?(mode_name),
    :stream_algorithm_mode => stream_algorithm_mode?(mode_name),
    :mode_version          => mode_version(mode_name)
  }
end

.mode_version(mode) ⇒ Fixnum

Returns the implementation version number of the specified mode.

Returns:

  • (Fixnum)


487
488
489
490
491
# File 'ext/mcrypt_wrapper.c', line 487

static VALUE mck_mode_version(VALUE self, VALUE mode)
{
    mode = to_s(mode);
    return INT2FIX(mcrypt_module_mode_version(RSTRING_PTR(mode), NULL));
}

.modesArray

Returns an array of all the supported mode names.

Returns:

  • (Array)


378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'ext/mcrypt_wrapper.c', line 378

static VALUE mck_modes(VALUE self)
{
    VALUE rv;
    int size, i;
    char **list;

    list = mcrypt_list_modes(NULL, &size);
    rv = rb_ary_new2(size);
    for (i = 0; i < size; i++) {
        rb_ary_push(rv, rb_str_new2(list[i]));
    }
    mcrypt_free_p(list, size);

    return rv;
}

.stream_algorithm?(algorithm_name) ⇒ Boolean

:call-seq:

Mcrypt.stream_algorithm?(algorithm_name) -> true or false

Returns true if the algorithm specified operates in bytes. This is mutually exclusive with block_algorithm?.

Returns:

  • (Boolean)


62
63
64
# File 'lib/mcrypt.rb', line 62

def stream_algorithm?(algorithm_name)
  ! block_algorithm?(algorithm_name)
end

.stream_algorithm_mode?(mode_name) ⇒ Boolean

:call-seq:

Mcrypt.stream_algorithm_mode?(mode_name) -> true or false

Returns true if the mode specified is for use with stream algorithms (e.g. ARCFOUR) This is mutually exclusive with block_algorithm_mode?.

Returns:

  • (Boolean)


101
102
103
# File 'lib/mcrypt.rb', line 101

def stream_algorithm_mode?(mode_name)
  ! block_algorithm_mode?(mode_name)
end

.stream_mode?(mode_name) ⇒ Boolean

:call-seq:

Mcrypt.stream_mode?(mode_name) -> true or false

Returns true if the mode specified operates in bytes. This is mutually exclusive with block_mode?.

Returns:

  • (Boolean)


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

def stream_mode?(mode_name)
  ! block_mode?(mode_name)
end

Instance Method Details

#algorithmObject

:call-seq:

algorithm -> String

The canonical name of the algorithm currently in use.



121
122
123
# File 'lib/mcrypt.rb', line 121

def algorithm
  @algorithm
end

#algorithm_versionFixnum

The numeric version of the algorithm implementation.

Returns:

  • (Fixnum)


328
329
330
331
332
333
334
# File 'ext/mcrypt_wrapper.c', line 328

static VALUE mc_algorithm_version(VALUE self)
{
    int version;
    VALUE algo = rb_iv_get(self,"@algorithm");
    version = mcrypt_module_algorithm_version(RSTRING_PTR(algo), NULL);
    return INT2FIX(version);
}

#block_algorithm?Boolean

True if the algorithm in use operates in blocks.

Returns:

  • (Boolean)


260
261
262
263
264
265
# File 'ext/mcrypt_wrapper.c', line 260

static VALUE mc_is_block_algorithm(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return TO_RB_BOOL(mcrypt_enc_is_block_algorithm(*box));
}

#block_algorithm_mode?Boolean

True if the encryption mode is for use with block algorithms.

Returns:

  • (Boolean)


286
287
288
289
290
291
# File 'ext/mcrypt_wrapper.c', line 286

static VALUE mc_is_block_algorithm_mode(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return TO_RB_BOOL(mcrypt_enc_is_block_algorithm_mode(*box));
}

#block_mode?Boolean

True if the encryption mode in use operates in blocks.

Returns:

  • (Boolean)


273
274
275
276
277
278
# File 'ext/mcrypt_wrapper.c', line 273

static VALUE mc_is_block_mode(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return TO_RB_BOOL(mcrypt_enc_is_block_mode(*box));
}

#block_sizeFixnum

Returns the block size (in bytes) for the algorithm in use. If it is a stream algorithm, this will be 1.

Returns:

  • (Fixnum)


230
231
232
233
234
235
# File 'ext/mcrypt_wrapper.c', line 230

static VALUE mc_block_size(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return INT2FIX(mcrypt_enc_get_block_size(*box));
}

#decrypt(ciphertext) ⇒ Object

Decrypts ciphertext and returns the decrypted result in one step. Use this for small inputs.

To save memory when decrypting larger inputs, process the ciphertext in chunks instead by using decrypt_more and decrypt_finish.



302
303
304
305
306
307
# File 'lib/mcrypt.rb', line 302

def decrypt(ciphertext)
  if @opened
    raise(RuntimeError, "cannot combine streaming use and atomic use")
  end
  decrypt_more(ciphertext) << decrypt_finish
end

#decrypt_finishObject

Completes the decryption process and returns the final plaintext chunk.



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/mcrypt.rb', line 336

def decrypt_finish
  open_td

  # no buffering/padding in stream mode
  return '' if stream_mode?

  # There should always be exactly zero or one block(s) in the buffer
  # at this point, because the input should be on block boundaries,
  # and we've consumed all available blocks but one in decrypt_more().
  if ! [0,block_size].include?(buffer.length)
    raise(RuntimeError, "input is not a multiple of the block size (#{block_size})")
  end

  plaintext = decrypt_generic(buffer.slice!(0,buffer.length))

  case padding
  when :pkcs
    unpad_pkcs(plaintext)
  when :zeros
    plaintext.sub!(/\0*\Z/,'')
  else
    plaintext
  end
ensure
  close_td
end

#decrypt_generic(ciphertext) ⇒ Object

:nodoc:



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'ext/mcrypt_wrapper.c', line 191

static VALUE mc_decrypt_generic(VALUE self, VALUE ciphertext)
{
    /* ciphertext is decrypted in-place */
    MCRYPT *box;
    VALUE plaintext;
    int rv;

    Data_Get_Struct(self, MCRYPT, box);

    /* rb_str_dup doesn't actually copy the buffer, hence rb_str_new */
    plaintext = rb_str_new(RSTRING_PTR(ciphertext), RSTRING_LEN(ciphertext));

    rv = mdecrypt_generic(*box, (void *)RSTRING_PTR(plaintext),
                          safe_len(RSTRING_LEN(plaintext)));
    if (rv != 0)
        rb_raise(cMcryptRuntimeError, "internal error: mdecrypt_generic returned %d", rv);
    return plaintext;
}

#decrypt_more(ciphertext) ⇒ Object

Decrypts ciphertext and returns a chunk of plaintext. Input to this function is buffered across calls until it is large enough to safely perform the decryption (as defined by the block size of algorithm in use). When there is enough data, a chunk of the decrypted data is returned. Otherwise it returns an empty string.



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/mcrypt.rb', line 315

def decrypt_more(ciphertext)
  open_td

  # no buffering in stream mode
  return decrypt_generic(ciphertext) if stream_mode?

  # buffer ciphertext and process in blocks.
  buffer << ciphertext
  blocks = buffer.length / block_size

  if blocks > 1
    # maintain at least one block of buffer, because it may be padding
    # that we'll need to process in decrypt_finish.
    decrypt_generic(buffer.slice!(0,(blocks - 1)*block_size))
  else
    # we don't have enough blocks yet. keep buffering
    ''
  end
end

#encrypt(plaintext) ⇒ Object

Encrypts plaintext and returns the encrypted result in one step. Use this for small inputs.

To save memory when encrypting larger inputs, process the plaintext in chunks instead by using encrypt_more and encrypt_finish.



244
245
246
247
248
249
# File 'lib/mcrypt.rb', line 244

def encrypt(plaintext)
  if @opened
    raise(RuntimeError, "cannot combine streaming use and atomic use")
  end
  encrypt_more(plaintext) << encrypt_finish
end

#encrypt_finishObject

Completes the encryption process and returns the final ciphertext chunk if any.



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/mcrypt.rb', line 276

def encrypt_finish
  open_td

  # no buffering/padding in stream mode
  return '' if stream_mode?

  # nothing to encrypt, no padding to add
  return '' if buffer.length == 0 && !padding

  buffer << padding_str
  ciphertext = encrypt_more('') # consume existing buffer

  if buffer.length > 0
    raise(RuntimeError, "internal error: buffer should be empty")
  end

  ciphertext
ensure
  close_td
end

#encrypt_generic(plaintext) ⇒ Object

:nodoc:



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'ext/mcrypt_wrapper.c', line 171

static VALUE mc_encrypt_generic(VALUE self, VALUE plaintext)
{
    /* plaintext is encrypted in-place */
    MCRYPT *box;
    VALUE ciphertext;
    int rv;

    Data_Get_Struct(self, MCRYPT, box);

    /* rb_str_dup doesn't actually copy the buffer, hence rb_str_new */
    ciphertext = rb_str_new(RSTRING_PTR(plaintext), RSTRING_LEN(plaintext));

    rv = mcrypt_generic(*box, (void *)RSTRING_PTR(ciphertext),
                        safe_len(RSTRING_LEN(ciphertext)));
    if (rv != 0)
        rb_raise(cMcryptRuntimeError, "internal error: mcrypt_generic returned %d", rv);
    return ciphertext;
}

#encrypt_more(plaintext) ⇒ Object

Encrypts plaintext and returns a chunk of ciphertext. Input to this function is buffered across calls until it is large enough to fill a complete block (as defined by the algorithm in use), at which point the encrypted data will be returned. If there is not enough buffer to encrypt an entire block, an empty string will be returned.



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/mcrypt.rb', line 256

def encrypt_more(plaintext)
  open_td

  return encrypt_generic(plaintext) if stream_mode?

  # buffer plaintext and process in blocks.
  # stream modes return 1 for block_size so this still works.
  buffer << plaintext
  blocks = buffer.length / block_size

  if blocks == 0
    # we don't have an entire block yet.  keep buffering
    ''
  else
    encrypt_generic(buffer.slice!(0,blocks*block_size))
  end
end

#generic_deinitObject

:nodoc:



162
163
164
165
166
167
168
# File 'ext/mcrypt_wrapper.c', line 162

static VALUE mc_generic_deinit(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    mcrypt_generic_deinit(*box);
    return Qnil;
}

#generic_initObject

:nodoc:



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'ext/mcrypt_wrapper.c', line 138

static VALUE mc_generic_init(VALUE self)
{
    /* ruby has already validated @key and @iv */
    VALUE key, iv;
    int rv;
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);

    key = rb_iv_get(self, "@key");
    iv  = rb_iv_get(self, "@iv");

    rv = mcrypt_generic_init(*box,
                             (void *)RSTRING_PTR(key),
                             safe_len(RSTRING_LEN(key)),
                             RSTR_N(iv));
    if (rv < 0) {
        const char *err = mcrypt_strerror(rv);
        rb_raise(cMcryptRuntimeError, "Could not initialize mcrypt: %s", err);
    }

    return Qnil;
}

#has_iv?Boolean

True if the the encryption mode uses an IV.

Returns:

  • (Boolean)


299
300
301
302
303
304
# File 'ext/mcrypt_wrapper.c', line 299

static VALUE mc_mode_has_iv(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return TO_RB_BOOL(mcrypt_enc_mode_has_iv(*box));
}

#ivObject

:call-seq:

iv -> String

The IV currently in use (raw binary).



145
146
147
# File 'lib/mcrypt.rb', line 145

def iv
  @iv
end

#iv=(new_iv) ⇒ Object

Set the initialization vector (IV) to be used. This is the final raw binary representation of the key (i.e. not base64 or hex-encoded).

The IV cannot be reassigned while the object is mid-encryption/decryption (e.g. after encrypt_more but before encrypt_finish). Attempting to do so will raise an exception.

If the mode in use does not use an IV and new_iv is non-nil, an exception will be raised to prevent you shooting yourself in the foot.



184
185
186
187
188
189
# File 'lib/mcrypt.rb', line 184

def iv=(new_iv)
  if @opened
    raise(RuntimeError, "cannot change IV mid-stream")
  end
  @iv = validate_iv(new_iv)
end

#iv_sizeFixnum?

Returns the IV size (in bytes) for the mode in use. If the mode does not use an IV, returns nil.

Returns:

  • (Fixnum, nil)


244
245
246
247
248
249
250
251
252
# File 'ext/mcrypt_wrapper.c', line 244

static VALUE mc_iv_size(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    if (mcrypt_enc_mode_has_iv(*box))
      return INT2FIX(mcrypt_enc_get_iv_size(*box));
    else
      return Qnil;
}

#keyObject

:call-seq:

key -> String

The key currently in use (raw binary).



137
138
139
# File 'lib/mcrypt.rb', line 137

def key
  @key
end

#key=(new_key) ⇒ Object

Set the cryptographic key to be used. This is the final raw binary representation of the key (i.e. not base64 or hex-encoded).

The key is validated to ensure it is an acceptable length for the algorithm currently in use (specified in call to new).

The key cannot be reassigned while the object is mid-encryption/decryption (e.g. after encrypt_more but before encrypt_finish). Attempting to do so will raise an exception.



167
168
169
170
171
172
# File 'lib/mcrypt.rb', line 167

def key=(new_key)
  if @opened
    raise(RuntimeError, "cannot change key mid-stream")
  end
  @key = validate_key(new_key)
end

#key_sizeFixnum

Returns the maximum key size for the algorithm in use.

Returns:

  • (Fixnum)


216
217
218
219
220
221
# File 'ext/mcrypt_wrapper.c', line 216

static VALUE mc_key_size(VALUE self)
{
    MCRYPT *box;
    Data_Get_Struct(self, MCRYPT, box);
    return INT2FIX(mcrypt_enc_get_key_size(*box));
}

#key_sizesArray

An array of the key sizes supported by the algorithm.

Returns:

  • (Array)


312
313
314
315
316
317
318
319
320
# File 'ext/mcrypt_wrapper.c', line 312

static VALUE mc_key_sizes(VALUE self)
{
    MCRYPT *box;
    int *sizes, num_of_sizes;
    Data_Get_Struct(self, MCRYPT, box);

    sizes = mcrypt_enc_get_supported_key_sizes(*box, &num_of_sizes);
    return enumerate_key_sizes(sizes, num_of_sizes, mcrypt_enc_get_key_size(*box));
}

#modeObject

:call-seq:

mode -> String

The name of the mode currently in use.



129
130
131
# File 'lib/mcrypt.rb', line 129

def mode
  @mode
end

#mode_versionFixnum

The numeric version of the encryption mode implementation.

Returns:

  • (Fixnum)


342
343
344
345
346
347
348
# File 'ext/mcrypt_wrapper.c', line 342

static VALUE mc_mode_version(VALUE self)
{
    int version;
    VALUE mode = rb_iv_get(self,"@mode");
    version = mcrypt_module_mode_version(RSTRING_PTR(mode), NULL);
    return INT2FIX(version);
}

#paddingObject

:call-seq:

padding -> String

One of false (default), :pkcs or :zeros. See padding=.



154
155
156
# File 'lib/mcrypt.rb', line 154

def padding
  @padding
end

#padding=(padding_type) ⇒ Object

Set the padding technique to be used. Most ciphers work in blocks, not bytes, so unless you know that the size of your plaintext will always be a multiple of the cipher’s block size, you’ll need to use some sort of padding.

padding_type.to_s should be one of:

“pkcs”,“pkcs5”,“pkcs7”

Use pkcs5/7 padding which is safe for use with arbitrary binary inputs (as opposed to null-terminated C-strings). Each byte of padding contains the number of bytes of padding used. For example, if 5 bytes of padding are needed, each byte has the value 0x05. See RFC 2315 for a more detailed explanation. Padding is always added to disambiguate an incomplete message from one that happens to fall on block boundaries.

“zeros”,“zeroes”

Pads the plaintext with NUL characters. This works fine with C- strings. Don’t use it with anything that might have other embedded nulls.

“none”

No padding is used. Will throw exceptions if the input size does not fall on block boundaries.

You can also pass true (which means “pkcs”) or false (no padding). No padding is used by default.

N.B. This is not a feature of libmcrypt but of this Ruby module.



221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/mcrypt.rb', line 221

def padding=(padding_type)
  @padding = case padding_type.to_s
    when "true", /\Apkcs[57]?\Z/
      @padding = :pkcs
    when /\Azeroe?s\Z/
      @padding = :zeros
    when "false", "none", ""
      @padding = false
    else
      raise(ArgumentError, "invalid padding type #{padding_type.to_s}")
    end
end

#stream_mode?Boolean

Returns true if the mode in use operates in bytes.

Returns:

  • (Boolean)


235
236
237
# File 'lib/mcrypt.rb', line 235

def stream_mode?
  ! block_mode?
end