GENERATE-PBE-KEY() inconsistent between .NET for large keys

Environment: 11.7.2

 

We need to enable encryption/decryption between C# and the Progress ABL, and have found some oddities between the implementations. The encryption model involves either side generating the encryption key based on a known seed value.

 

However, we've found that the GENERATE-PBE-KEY() function does not match the output of the PasswordDeriveBytes implementation from .NET, for keys larger than 128-bits. I've checked the example code from the Knowledge Base article[1], and it works for anything up to 128-bit key size. If I change the ABL code to use AES_CBC_192 or AES_CBC_256 encryption algorithm, the key values are generated differently:

 

Key size: 128 (AES_CBC_128) (from the example, and works)

ABL: ML06Y67hc5E4iqM0RiCXDQ==

C#: ML06Y67hc5E4iqM0RiCXDQ==

 

Key size: 192 (AES_CBC_192)

ABL: ML06Y67hc5E4iqM0RiCXDXW5Z1dAmcZi

C#: ML06Y67hc5E4iqM0RiCXDXW5Z1fhRcrH

 

Key size: 256 (AES_CBC_256)

ABL: ML06Y67hc5E4iqM0RiCXDXW5Z1dAmcZiuYcLkuu7DpM=

C#: ML06Y67hc5E4iqM0RiCXDXW5Z1fhRcrHLqG2HSv1/GM=

 

The difference is both cases starts after 26 characters (156 bits) - not sure if that is relevant. This applies to any of the _192 or _256 algorithms from the SYMMETRIC-SUPPORT list, not just the AES cipher.

 

[1] - https://knowledgebase.progress.com/articles/Article/000041878

 

Is this something that is known, or is there something else that needs to be adjusted to ensure the same input generates the same key across multiple applications/languages?

 

UPDATE: It appears that the core problem is that the neither the ABL implementation of GENERATE-PBE-KEY(), or the C# version of the PasswordDeriveBytes method, implement the PKCS1 algorithm correctly. Both allow for keys longer than accounted for. F

 

From RFC2898, section 5.1 (source: https://tools.ietf.org/html/rfc2898#section-5.1)

 

"The length of the derived key is bounded by the length of the hash function output, which is 16 octets for MD2 and MD5 and 20 octets for SHA-1."

 

This means that the GENERATE-PBE-KEY() function should error if requesting a key longer than 160-bits, rather than return a valid key. The same applies for C# (it uses a proprietary implementation to fill in the extra bytes).

 

This then leads to the question: what logic/algorithm is the OpenEdge implementation using to stretch the key to the requested length? 

It is not using the same implementation as C# (as observed from the results), but it is using a deterministic algorithm (as the same code will produce the same key on different OpenEge installation and versions).


  • Daniel Becroft (Customer)

    Just in case anyone comes across this and needs an answer. OpenEdge uses the OpenSSL encryption library under the hood. Specifically, the GENERATE-PBE-KEY() method returns the same output as OpenSSL's EVP_BytesToKey method. There's a C# version available here on Github (not my code).

    Selected as Best
  • Daniel Becroft (Customer)

    Just in case anyone comes across this and needs an answer. OpenEdge uses the OpenSSL encryption library under the hood. Specifically, the GENERATE-PBE-KEY() method returns the same output as OpenSSL's EVP_BytesToKey method. There's a C# version available here on Github (not my code).

    Selected as Best