Consider using byte[] instead of string for keys and data
kschulst opened this issue · 4 comments
The Mysto FPE library familiy are using String internally and in the method signatures. It would probably be a big change or addition to these contracts, but would you consider accepting a PR for using byte[] instead (or at least in the method interfaces)?
Using String instead of byte[] for handling cryptographic keys or secrets in Java can have several security implications:
Immutability: Strings in Java are immutable, which means that once a String is created, it cannot be changed. Consequently, a cryptographic key or secret stored as a String will remain in memory until garbage collection occurs, which may take an indefinite amount of time. This exposes the sensitive information to a higher risk of being leaked or exploited through memory-based attacks. On the other hand, byte arrays are mutable, allowing the contents to be explicitly overwritten or zeroed out when they are no longer needed, reducing the risk of sensitive information leakage.
String Interning: Java maintains a pool of unique strings called the "string constant pool." When a new String object is created, it may be added to this pool, increasing the chances of sensitive information being exposed or leaked. With byte arrays, this risk is significantly reduced as they are not pooled.
Encoding issues: When working with cryptographic keys or secrets, it is essential to ensure that the data is handled as raw binary data. Using Strings may inadvertently introduce encoding issues (e.g., converting between character sets), which could lead to data corruption or incorrect processing. Byte arrays, on the other hand, naturally represent raw binary data and do not suffer from encoding-related issues.
Memory representation: Strings store their data as character arrays, which are typically twice the size of byte arrays because Java uses UTF-16 encoding. This may lead to increased memory usage when handling large cryptographic keys or secrets.
To mitigate these security risks, it is generally advisable to use byte arrays or other mutable data structures for handling cryptographic keys or secrets in Java. Additionally, one could also use specialized libraries like Java's javax.crypto.SecretKey
interface, which is designed specifically for handling cryptographic keys securely.
We are implementing an FPE primitive for Google Tink, and in Google Tink all primitives are designed to accept and output byte[] arrays instead of other data types. This is because byte[] is a universally supported data type that can be easily serialized, transported, and stored in various formats. To be compliant with this philosophy, when working with the Mysto FPE libraries, we end up doing a lot of byte[]->string->byte[] conversions, which might have performance implications.
The following are some of rationale behind the Google Tink byte[] design decision:
Security: byte[] arrays are a basic unit of data in cryptographic operations. Using byte[] arrays ensures that data is being processed at the lowest possible level, which can help ensure that the cryptographic operations are secure.
Interoperability: byte[] arrays can be easily serialized and deserialized in a platform-independent way. This makes it easier to transport and share data between different platforms and programming languages.
Flexibility: byte[] arrays can represent any type of data, from strings to integers to binary data. This makes them a versatile and flexible data type that can be used in a wide range of applications.
While it may be more convenient to use other data types in some cases, using byte[] arrays provides a consistent and reliable approach to handling data in cryptographic operations. By sticking to a standard data type, Tink can provide a simpler and more secure way to implement cryptographic primitives.
@kschulst you make an excellent argument. The Mysto clang version here uses OPENSSL_clear_free() for exactly this reason - to overwrite the data before releasing the memory.
@kschulst would adding the following suite your needs?
- public FF3Cipher(byte[] key, String tweak)
- public FF3Cipher(byte[] key, String tweak, String alphabet)
- public FF3Cipher(byte[] key, String tweak, int radix)