Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
instance method
OpenSSL::Cipher#update
(::String data, ?::String buffer) -> ::String
cipher.update(data [, buffer]) → string or buffer
ext/openssl/ossl_cipher.c
View on GitHub ↗
static VALUE
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
{
EVP_CIPHER_CTX *ctx;
unsigned char *in;
rb_len_t in_len, out_len;
VALUE data, str;
rb_scan_args(argc, argv, "11", &data, &str);
if (!RTEST(rb_attr_get(self, id_key_set)))
ossl_raise(eCipherError, "key not set");
StringValue(data);
in = (unsigned char *)RSTRING_PTR(data);
in_len = RSTRING_LEN(data);
GetCipher(self, ctx);
/*
* As of OpenSSL 3.2, there is no reliable way to determine the required
* output buffer size for arbitrary cipher modes.
* https://github.com/openssl/openssl/issues/22628
*
* in_len+block_size is usually sufficient, but AES key wrap with padding
* ciphers require in_len+15 even though they have a block size of 8 bytes.
*
* Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers
* currently implemented in OpenSSL, but this can change in the future.
*/
if (in_len > RB_LEN_MAX - EVP_MAX_BLOCK_LENGTH) {
ossl_raise(rb_eRangeError,
"data too big to make output buffer: %"PRIdLEN" bytes",
in_len);
}
out_len = in_len + EVP_MAX_BLOCK_LENGTH;
if (NIL_P(str))
str = rb_str_buf_new(out_len);
else {
StringValue(str);
if ((rb_len_t)rb_str_capacity(str) >= out_len)
rb_str_modify(str);
else
rb_str_modify_expand(str, out_len - RSTRING_LEN(str));
}
if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str),
&out_len, in, in_len))
ossl_raise(eCipherError, "EVP_CipherUpdate");
rb_str_set_len(str, out_len);
return str;
}
Encrypts data in a streaming fashion. Hand consecutive blocks of data to the update method in order to encrypt it. Returns the encrypted data chunk. When done, the output of Cipher#final should be additionally added to the result.
If buffer is given, the encryption/decryption result will be written to it. buffer will be resized automatically.
NOTE: When decrypting using an AEAD cipher, the integrity of the output is not verified until final has been called.