Feature Request: Add AES-128-CFB Mode Support to pgcrypto
Dear PostgreSQL Development Team,
I would like to request the addition of support for the *AES-128-CFB* mode
in the pgcrypto extension. Currently, pgcrypto supports AES encryption
modes like ECB and CBC, but it does not include CFB mode, which is
essential for certain use cases.
In managed environments such as *Azure Database for PostgreSQL - Flexible
Server*, users are unable to create or install custom extensions. This
restriction makes it challenging to work with encrypted data that relies on
AES-128-CFB, as we cannot use custom solutions to handle this algorithm.
Adding CFB mode support to pgcrypto would address this limitation and
expand its usability in managed PostgreSQL environments.
Implementing AES-128-CFB in pgcrypto should require only minimal changes,
as it is already built on OpenSSL, which supports the CFB mode natively.
Including this functionality would also align pgcrypto with the principle
of providing robust cryptographic support, similar to other database
solutions.
Why This Matters:
1. *Compatibility*: Many existing systems encrypt data using
AES-128-CFB, and without native support in pgcrypto, PostgreSQL users
must resort to inefficient workarounds.
2. *Consistency*: pgcrypto already supports other AES modes (e.g., ECB,
CBC). Including CFB would ensure that its AES capabilities are complete.
3. *Ease of Implementation*: OpenSSL already provides a straightforward
API for AES-128-CFB, so adding it to pgcrypto should require only a few
lines of code.
This enhancement would greatly benefit users in managed environments and
improve the flexibility of PostgreSQL as a whole.
Thank you for considering this request. I would be happy to assist in
testing or providing further information if needed.
Best regards,
Vladyslav Nebozhyn
On 28 Jan 2025, at 11:46, Vladyslav Nebozhyn <vlad@liberatii.com> wrote:
• Ease of Implementation: OpenSSL already provides a straightforward API for AES-128-CFB, so adding it to pgcrypto should require only a few lines of code.
IIRC we already support CFB for Blowfish so I think it would be quite easy to
add. If you propose a patch for adding this I can volunteer to review it.
--
Daniel Gustafsson
Hi Daniel Gustafsson and Vladyslav Nebozhyn,
I created a patch for CFB mode for AES encryption. Please have a look
and let me know what you think.
Patch covers implementation, tests and documentation changes.
OpenSSL profives aes-cfb1, aes-cfb8 and aes-cfb128 modes where aes-cfb
defaults to aes-cfb128. For simplicity I only added aes-cfb, which is
the most common method used, lower number of bits will introduce
performance degradation, but if it's desirable I can add them as well.
--
Umar Hayat
Bitnine (https://bitnine.net/)
Attachments:
v0-0001-pgcrypto-aes-cfb-mode.patchapplication/octet-stream; name=v0-0001-pgcrypto-aes-cfb-mode.patchDownload
From de1e4a452189801259bcd0778d007010d52fe4a7 Mon Sep 17 00:00:00 2001
From: Umar Hayat <postgresql.wizard@gmail.com>
Date: Wed, 29 Jan 2025 18:49:19 +0900
Subject: [PATCH] pgcrypto: add AES encryption CFB mode support
---
contrib/pgcrypto/expected/rijndael.out | 118 +++++++++++++++++++++++++
contrib/pgcrypto/openssl.c | 39 ++++++++
contrib/pgcrypto/sql/rijndael.sql | 53 +++++++++++
doc/src/sgml/pgcrypto.sgml | 5 ++
4 files changed, 215 insertions(+)
diff --git a/contrib/pgcrypto/expected/rijndael.out b/contrib/pgcrypto/expected/rijndael.out
index 015ba4430d9..28e28b989fd 100644
--- a/contrib/pgcrypto/expected/rijndael.out
+++ b/contrib/pgcrypto/expected/rijndael.out
@@ -135,3 +135,121 @@ select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes')
Lets try a longer message.
(1 row)
+-- cfb
+SELECT encrypt(
+'\x00112233445566778899aabbccddeeff',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
+'aes-cfb/pad:none');
+ encrypt
+------------------------------------
+ \xf28122856e1cf9a7216a30d111f3997f
+(1 row)
+
+-- without padding, input not multiple of block size
+SELECT encrypt(
+'\x00112233445566778899aabbccddeeff00',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
+'aes-cfb/pad:none');
+ encrypt
+--------------------------------------
+ \xf28122856e1cf9a7216a30d111f3997fcb
+(1 row)
+
+-- key padding
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405',
+'aes-cfb');
+ encrypt
+--------------
+ \x8145d1a0ef
+(1 row)
+
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405060708090a0b0c0d0e0f10111213',
+'aes-cfb');
+ encrypt
+--------------
+ \x52642c3b9c
+(1 row)
+
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b',
+'aes-cfb');
+ encrypt
+--------------
+ \xc93b4468a4
+(1 row)
+
+-- empty data
+select encrypt('', 'foo', 'aes-cfb');
+ encrypt
+---------
+ \x
+(1 row)
+
+-- 10 bytes key
+select encrypt('foo', '0123456789', 'aes-cfb');
+ encrypt
+----------
+ \x6f8ced
+(1 row)
+
+-- 22 bytes key
+select encrypt('foo', '0123456789012345678901', 'aes-cfb');
+ encrypt
+----------
+ \xfb47d2
+(1 row)
+
+-- decrypt
+select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb'), '0123456', 'aes-cfb'), 'escape');
+ encode
+--------
+ foo
+(1 row)
+
+-- data not multiple of block size
+select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb') || '\x00'::bytea, '0123456', 'aes-cfb'), 'escape');
+ encode
+---------
+ foo\337
+(1 row)
+
+-- bad padding
+-- (The input value is the result of encrypt_iv('abcdefghijklmnopqrstuvwxyz', '0123456', 'abcd', 'aes-cfb')
+-- with the 16th byte changed (s/c5/d5/) to corrupt the padding of the last block.)
+select encode(decrypt_iv('\xf9ad6817cb58d31dd9ba6571fbc4f55d56f65b631f0f437cb828', '0123456', 'abcd', 'aes-cfb'), 'escape');
+ encode
+-------------------------------------------------
+ abcdefghijklmnoq\243:\205o\x7F\x05z\276\x07\332
+(1 row)
+
+-- iv
+select encrypt_iv('foo', '0123456', 'abcd', 'aes-cfb');
+ encrypt_iv
+------------
+ \xfea064
+(1 row)
+
+select encode(decrypt_iv('\xfea064', '0123456', 'abcd', 'aes-cfb'), 'escape');
+ encode
+--------
+ foo
+(1 row)
+
+-- long message
+select encrypt('Lets try a longer message.', '0123456789', 'aes-cfb');
+ encrypt
+--------------------------------------------------------
+ \x4586f6c6351055051f723b1b0aad52c877eaf0c421d18fd73a28
+(1 row)
+
+select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'), '0123456789', 'aes-cfb'), 'escape');
+ encode
+----------------------------
+ Lets try a longer message.
+(1 row)
+
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 75f40a2d034..f179e80c842 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -617,6 +617,36 @@ ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv
return err;
}
+static int
+ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
+{
+ OSSLCipher *od = c->ptr;
+ int err;
+
+ err = ossl_aes_init(c, key, klen, iv);
+ if (err)
+ return err;
+
+ switch (od->klen)
+ {
+ case 128 / 8:
+ od->evp_ciph = EVP_aes_128_cfb();
+ break;
+ case 192 / 8:
+ od->evp_ciph = EVP_aes_192_cfb();
+ break;
+ case 256 / 8:
+ od->evp_ciph = EVP_aes_256_cfb();
+ break;
+ default:
+ /* shouldn't happen */
+ err = PXE_CIPHER_INIT;
+ break;
+ }
+
+ return err;
+}
+
/*
* aliases
*/
@@ -636,6 +666,7 @@ static PX_Alias ossl_aliases[] = {
{"rijndael", "aes-cbc"},
{"rijndael-cbc", "aes-cbc"},
{"rijndael-ecb", "aes-ecb"},
+ {"rijndael-cfb", "aes-cfb"},
{NULL}
};
@@ -707,6 +738,13 @@ static const struct ossl_cipher ossl_aes_cbc = {
128 / 8, 256 / 8
};
+static const struct ossl_cipher ossl_aes_cfb = {
+ ossl_aes_cfb_init,
+ NULL, /* EVP_aes_XXX_cfb(), determined in init
+ * function */
+ 128 / 8, 256 / 8
+};
+
/*
* Special handlers
*/
@@ -728,6 +766,7 @@ static const struct ossl_cipher_lookup ossl_cipher_types[] = {
{"cast5-cbc", &ossl_cast_cbc},
{"aes-ecb", &ossl_aes_ecb},
{"aes-cbc", &ossl_aes_cbc},
+ {"aes-cfb", &ossl_aes_cfb},
{NULL}
};
diff --git a/contrib/pgcrypto/sql/rijndael.sql b/contrib/pgcrypto/sql/rijndael.sql
index a2766419980..de4e4da5e29 100644
--- a/contrib/pgcrypto/sql/rijndael.sql
+++ b/contrib/pgcrypto/sql/rijndael.sql
@@ -70,3 +70,56 @@ select encode(decrypt_iv('\x2c24cb7da91d6d5699801268b0f5adad', '0123456', 'abcd'
-- long message
select encrypt('Lets try a longer message.', '0123456789', 'aes');
select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes'), '0123456789', 'aes'), 'escape');
+
+-- cfb
+SELECT encrypt(
+'\x00112233445566778899aabbccddeeff',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
+'aes-cfb/pad:none');
+
+-- without padding, input not multiple of block size
+SELECT encrypt(
+'\x00112233445566778899aabbccddeeff00',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
+'aes-cfb/pad:none');
+
+-- key padding
+
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405',
+'aes-cfb');
+
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405060708090a0b0c0d0e0f10111213',
+'aes-cfb');
+
+SELECT encrypt(
+'\x0011223344',
+'\x000102030405060708090a0b0c0d0e0f101112131415161718191a1b',
+'aes-cfb');
+
+-- empty data
+select encrypt('', 'foo', 'aes-cfb');
+-- 10 bytes key
+select encrypt('foo', '0123456789', 'aes-cfb');
+-- 22 bytes key
+select encrypt('foo', '0123456789012345678901', 'aes-cfb');
+
+-- decrypt
+select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb'), '0123456', 'aes-cfb'), 'escape');
+-- data not multiple of block size
+select encode(decrypt(encrypt('foo', '0123456', 'aes-cfb') || '\x00'::bytea, '0123456', 'aes-cfb'), 'escape');
+-- bad padding
+-- (The input value is the result of encrypt_iv('abcdefghijklmnopqrstuvwxyz', '0123456', 'abcd', 'aes-cfb')
+-- with the 16th byte changed (s/c5/d5/) to corrupt the padding of the last block.)
+select encode(decrypt_iv('\xf9ad6817cb58d31dd9ba6571fbc4f55d56f65b631f0f437cb828', '0123456', 'abcd', 'aes-cfb'), 'escape');
+
+-- iv
+select encrypt_iv('foo', '0123456', 'abcd', 'aes-cfb');
+select encode(decrypt_iv('\xfea064', '0123456', 'abcd', 'aes-cfb'), 'escape');
+
+-- long message
+select encrypt('Lets try a longer message.', '0123456789', 'aes-cfb');
+select encode(decrypt(encrypt('Lets try a longer message.', '0123456789', 'aes-cfb'), '0123456789', 'aes-cfb'), 'escape');
diff --git a/doc/src/sgml/pgcrypto.sgml b/doc/src/sgml/pgcrypto.sgml
index a4d035eabdd..dc677442939 100644
--- a/doc/src/sgml/pgcrypto.sgml
+++ b/doc/src/sgml/pgcrypto.sgml
@@ -1082,6 +1082,11 @@ decrypt_iv(data bytea, key bytea, iv bytea, type text) returns bytea
<literal>cbc</literal> — next block depends on previous (default)
</para>
</listitem>
+ <listitem>
+ <para>
+ <literal>cfb</literal> — next block depends on previous encrypted block
+ </para>
+ </listitem>
<listitem>
<para>
<literal>ecb</literal> — each block is encrypted separately (for
--
2.31.0
Dear Daniel Gustafsson,
Thank you for your response and for offering to review the patch. I
really appreciate your time and willingness to assist with this!
I've prepared a patch to add AES-CFB support to pgcrypto, following
the existing structure used for other AES modes. Integrating it for
AES requires only minimal modifications.
The patch is included below for reference and is also attached as a
file (Encription-AES-CFB-is-added.patch). Please let me know if any
adjustments are needed. I’d be happy to refine it further based on
your feedback.
Patch:
From 2e246ed3c3f8909c42a192e0bb07535713987e80 Mon Sep 17 00:00:00 2001
From: vlne <vlad@liberatii.com>
Date: Wed, 29 Jan 2025 11:42:56 +0200
Subject: [PATCH] Encription AES-CFB is added
---
contrib/pgcrypto/openssl.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 75f40a2d03..184aa1cac3 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -617,6 +617,36 @@ ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key,
unsigned klen, const uint8 *iv
return err;
}
+static int
+ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen,
const uint8 *iv)
+{
+ OSSLCipher *od = c->ptr;
+ int err;
+
+ err = ossl_aes_init(c, key, klen, iv);
+ if (err)
+ return err;
+
+ switch (od->klen)
+ {
+ case 128 / 8:
+ od->evp_ciph = EVP_aes_128_cfb();
+ break;
+ case 192 / 8:
+ od->evp_ciph = EVP_aes_192_cfb();
+ break;
+ case 256 / 8:
+ od->evp_ciph = EVP_aes_256_cfb();
+ break;
+ default:
+ /* shouldn't happen */
+ err = PXE_CIPHER_INIT;
+ break;
+ }
+
+ return err;
+}
+
/*
* aliases
*/
@@ -707,6 +737,13 @@ static const struct ossl_cipher ossl_aes_cbc = {
128 / 8, 256 / 8
};
+static const struct ossl_cipher ossl_aes_cfb = {
+ ossl_aes_cfb_init,
+ NULL, /* EVP_aes_XXX_cfb(), determined in init
+ * function */
+ 128 / 8, 256 / 8
+};
+
/*
* Special handlers
*/
@@ -728,6 +765,7 @@ static const struct ossl_cipher_lookup
ossl_cipher_types[] = {
{"cast5-cbc", &ossl_cast_cbc},
{"aes-ecb", &ossl_aes_ecb},
{"aes-cbc", &ossl_aes_cbc},
+ {"aes-cfb", &ossl_aes_cfb},
{NULL}
};
--
2.40.1.windows.1
Best regards,
Vladyslav Nebozhyn
<br><div class="gmail_quote gmail_quote_container"><div dir="ltr"
class="gmail_attr">On Tue, 28 Jan 2025 at 14:14, Daniel Gustafsson
<daniel@yesql.se> wrote:<br></div><blockquote
class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left: 1px
solid rgb(204, 204, 204); padding-left: 1ex;">> On 28 Jan 2025, at
11:46, Vladyslav Nebozhyn <<a href="mailto:vlad@liberatii.com"
target="_blank">vlad@liberatii.com</a>> wrote:<br>
<br>
> • Ease of Implementation: OpenSSL already
provides a straightforward API for AES-128-CFB, so adding it to
pgcrypto should require only a few lines of code.<br>
<br>
IIRC we already support CFB for Blowfish so I think it would be quite
easy to<br>
add. If you propose a patch for adding this I can volunteer to
review it.<br>
<br>
--<br>
Daniel Gustafsson<br>
<br>
</blockquote></div>
Attachments:
Encription-AES-CFB-is-added.patchapplication/octet-stream; name=Encription-AES-CFB-is-added.patchDownload
From 2e246ed3c3f8909c42a192e0bb07535713987e80 Mon Sep 17 00:00:00 2001
From: vlne <vlad@liberatii.com>
Date: Wed, 29 Jan 2025 11:42:56 +0200
Subject: [PATCH] Encription AES-CFB is added
---
contrib/pgcrypto/openssl.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c
index 75f40a2d03..184aa1cac3 100644
--- a/contrib/pgcrypto/openssl.c
+++ b/contrib/pgcrypto/openssl.c
@@ -617,6 +617,36 @@ ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv
return err;
}
+static int
+ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
+{
+ OSSLCipher *od = c->ptr;
+ int err;
+
+ err = ossl_aes_init(c, key, klen, iv);
+ if (err)
+ return err;
+
+ switch (od->klen)
+ {
+ case 128 / 8:
+ od->evp_ciph = EVP_aes_128_cfb();
+ break;
+ case 192 / 8:
+ od->evp_ciph = EVP_aes_192_cfb();
+ break;
+ case 256 / 8:
+ od->evp_ciph = EVP_aes_256_cfb();
+ break;
+ default:
+ /* shouldn't happen */
+ err = PXE_CIPHER_INIT;
+ break;
+ }
+
+ return err;
+}
+
/*
* aliases
*/
@@ -707,6 +737,13 @@ static const struct ossl_cipher ossl_aes_cbc = {
128 / 8, 256 / 8
};
+static const struct ossl_cipher ossl_aes_cfb = {
+ ossl_aes_cfb_init,
+ NULL, /* EVP_aes_XXX_cfb(), determined in init
+ * function */
+ 128 / 8, 256 / 8
+};
+
/*
* Special handlers
*/
@@ -728,6 +765,7 @@ static const struct ossl_cipher_lookup ossl_cipher_types[] = {
{"cast5-cbc", &ossl_cast_cbc},
{"aes-ecb", &ossl_aes_ecb},
{"aes-cbc", &ossl_aes_cbc},
+ {"aes-cfb", &ossl_aes_cfb},
{NULL}
};
--
2.40.1.windows.1
Dear Umar,
I sincerely apologize for missing your email earlier. I truly
appreciate the time and effort you put into creating the patch—it
looks great! Thank you for your work on this and for contributing to
the solution so quickly.
I’m really glad to see this enhancement being added to pgcrypto, and I
appreciate your support in making it happen. Thanks again!
Best regards,
Vladyslav Nebozhyn
Show quoted text
On Wed, 29 Jan 2025 at 12:11, Vladyslav Nebozhyn <vlad@liberatii.com> wrote:
Dear Daniel Gustafsson,
Thank you for your response and for offering to review the patch. I
really appreciate your time and willingness to assist with this!I've prepared a patch to add AES-CFB support to pgcrypto, following
the existing structure used for other AES modes. Integrating it for
AES requires only minimal modifications.The patch is included below for reference and is also attached as a
file (Encription-AES-CFB-is-added.patch). Please let me know if any
adjustments are needed. I’d be happy to refine it further based on
your feedback.Patch:
From 2e246ed3c3f8909c42a192e0bb07535713987e80 Mon Sep 17 00:00:00 2001
From: vlne <vlad@liberatii.com>
Date: Wed, 29 Jan 2025 11:42:56 +0200
Subject: [PATCH] Encription AES-CFB is added---
contrib/pgcrypto/openssl.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index 75f40a2d03..184aa1cac3 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.c @@ -617,6 +617,36 @@ ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv return err; }+static int +ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv) +{ + OSSLCipher *od = c->ptr; + int err; + + err = ossl_aes_init(c, key, klen, iv); + if (err) + return err; + + switch (od->klen) + { + case 128 / 8: + od->evp_ciph = EVP_aes_128_cfb(); + break; + case 192 / 8: + od->evp_ciph = EVP_aes_192_cfb(); + break; + case 256 / 8: + od->evp_ciph = EVP_aes_256_cfb(); + break; + default: + /* shouldn't happen */ + err = PXE_CIPHER_INIT; + break; + } + + return err; +} + /* * aliases */ @@ -707,6 +737,13 @@ static const struct ossl_cipher ossl_aes_cbc = { 128 / 8, 256 / 8 };+static const struct ossl_cipher ossl_aes_cfb = { + ossl_aes_cfb_init, + NULL, /* EVP_aes_XXX_cfb(), determined in init + * function */ + 128 / 8, 256 / 8 +}; + /* * Special handlers */ @@ -728,6 +765,7 @@ static const struct ossl_cipher_lookup ossl_cipher_types[] = { {"cast5-cbc", &ossl_cast_cbc}, {"aes-ecb", &ossl_aes_ecb}, {"aes-cbc", &ossl_aes_cbc}, + {"aes-cfb", &ossl_aes_cfb}, {NULL} };--
2.40.1.windows.1Best regards,
Vladyslav Nebozhyn
<br><div class="gmail_quote gmail_quote_container"><div dir="ltr"
class="gmail_attr">On Tue, 28 Jan 2025 at 14:14, Daniel Gustafsson
<daniel@yesql.se> wrote:<br></div><blockquote
class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left: 1px
solid rgb(204, 204, 204); padding-left: 1ex;">> On 28 Jan 2025, at
11:46, Vladyslav Nebozhyn <<a href="mailto:vlad@liberatii.com"
target="_blank">vlad@liberatii.com</a>> wrote:<br>
<br>
> • Ease of Implementation: OpenSSL already
provides a straightforward API for AES-128-CFB, so adding it to
pgcrypto should require only a few lines of code.<br>
<br>
IIRC we already support CFB for Blowfish so I think it would be quite
easy to<br>
add. If you propose a patch for adding this I can volunteer to
review it.<br>
<br>
--<br>
Daniel Gustafsson<br>
<br>
</blockquote></div>
Hi Vladyslav,
No Problem, I also did not realize that you will be implementing it.
So I spent a couple of hours and provided a patch.
Also created commitfest entry as well, Please do review the patch and
let me know if this is sufficient at least for your use case.
Regards,
Umar Hayat
Bitnine (https://bitnine.net/)
On 2025-Jan-29, Umar Hayat wrote:
Hi Daniel Gustafsson and Vladyslav Nebozhyn,
I created a patch for CFB mode for AES encryption. Please have a look
and let me know what you think.
Patch covers implementation, tests and documentation changes.OpenSSL profives aes-cfb1, aes-cfb8 and aes-cfb128 modes where aes-cfb
defaults to aes-cfb128. For simplicity I only added aes-cfb, which is
the most common method used, lower number of bits will introduce
performance degradation, but if it's desirable I can add them as well.
I kicked the tires on this by encrypting a file with
openssl aes-128-cfb -K afe908123efcba901230afe908eb5a04 -iv 912387caedade123912387c7ec0b9d0f -pbkdf2
then importing that into a bytea column. Then I can sort-of obtain the
file back with
select decrypt_iv from data, decrypt_iv(a, '\xafe908123efcba901230', '\x912387caedade123', 'aes-cfb');
... Except that appears that openssl will encode UTF8 characters in my file
as \ooo octal escapes in the encrypted output, which is really weird, so
the file doesn't roundtrip exactly. Maybe this is a pgcrypto shortcoming, not
sure. The final output looks like this (shortened):
=# select decrypt_iv from data, decrypt_iv(a, '\xafe908123efcba901230afe908eb5a04', '\x912387caedade123912387c7ec0b9d0f', 'aes-cfb');
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────>
\302\241Hoy ha sido un d\303\255a genial! Era el cumple de la abuela, que es la mam\303\241 de mam\303\241,
Anyway, at least the bytes appear to be interpreted the same by both
openssl and this new function, so that's good news.
--
Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
"Having your biases confirmed independently is how scientific progress is
made, and hence made our great society what it is today" (Mary Gardiner)
On 5 Feb 2025, at 18:24, Álvaro Herrera <alvherre@alvh.no-ip.org> wrote:
Anyway, at least the bytes appear to be interpreted the same by both
openssl and this new function, so that's good news.
Thanks for confirming. Short of a very small doc change (which I don't have
handy on this laptop) I think this patch is ready. I wish we had a better way
of adding support for ciphers in OpenSSL but it's not the responsibility of
this patch to solve that.
--
Daniel Gustafsson
On 5 Feb 2025, at 18:28, Daniel Gustafsson <daniel@yesql.se> wrote:
On 5 Feb 2025, at 18:24, Álvaro Herrera <alvherre@alvh.no-ip.org> wrote:
Anyway, at least the bytes appear to be interpreted the same by both
openssl and this new function, so that's good news.Thanks for confirming. Short of a very small doc change (which I don't have
handy on this laptop) I think this patch is ready. I wish we had a better way
of adding support for ciphers in OpenSSL but it's not the responsibility of
this patch to solve that.
I took another look at this, fixed the trivial detail in the docs, and applied
it. Thanks for the submission!
--
Daniel Gustafsson