Skip to content

Commit

Permalink
Deprecate old Secure Cell API
Browse files Browse the repository at this point in the history
Mark almost all Secure Cell API as deprecated. Provide replacement
instructions where relevant. Suppress deprecation warnings in our own
code which tests old API usage and has to rely on public constants that
we cannot make private now.

Most of the deprecated API has more or less direct counterparts in the
new API. Though, there are no counterparts to consutructors that accept
no symmetric key or methods that accept one.
  • Loading branch information
ilammy committed May 6, 2020
1 parent e787546 commit 486e214
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 2 deletions.
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,40 @@ _Code:_
such as generated by `SymmetricKey` ([#565](https://github.com/cossacklabs/themis/pull/565)).
Use passphrase API with human-readable passphrases.

- **Deprecated API**

- Secure Cell has received API overhaul which deprecates old API
([#636](https://github.com/cossacklabs/themis/pull/636)).

The following items are deprecated:

- Constructors:
- `new SecureCell(int mode)`
- `new SecureCell(byte[] key)`
- `new SecureCell(byte[] key, int mode)`
- `new SecureCell(String password)` ⚠️ **not secure**
- `new SecureCell(String password, int mode)` ⚠️ **not secure**
- Methods:
- `protect(byte[] key, byte[] context, byte[] data)`
- `protect(byte[] constext, byte[] data)`
- `protect(String password, String context, byte[] data)` ⚠️ **not secure**
- `protect(String context, byte[] data)`
- `unprotect(byte[] key, byte[] context, SecureCellData protected)`
- `unprotect(byte[] context, SecureCellData protected)`
- `unprotect(String password, String context, SecureCellData protected)` ⚠️ **not secure**
- `unprotect(String context, SecureCellData protected)`
- Constants:
- `SecureCell.MODE_SEAL`
- `SecureCell.MODE_TOKEN_PROTECT`
- `SecureCell.MODE_CONTEXT_IMPRINT`

Some methods are not secure when used with short passphrases,
consider using new passphrase API instead.
Other methods have easier to use replacements in the new API,
consider using them instead.

Deprecated API is still supported, there are no plans for its removal.

- **Node.js**

- New class `SymmetricKey` can be used to generate symmetric keys for Secure Cell ([#562](https://github.com/cossacklabs/themis/pull/562)).
Expand Down
95 changes: 94 additions & 1 deletion src/wrappers/themis/java/com/cossacklabs/themis/SecureCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,16 @@ public static ContextImprint ContextImprintWithKey(byte[] key) {
* Creates new SecureCell in specified mode
* @param SecureCell mode
* @throws InvalidArgumentException when unsupported mode is specified
* @deprecated since JavaThemis 0.13
* <p>
* Select the mode with an appropriate static factory method instead:
* <ul>
* <li>{@link #SealWithKey(SymmetricKey)}
* <li>{@link #TokenProtectWithKey(SymmetricKey)}
* <li>{@link #ContextImprintWithKey(SymmetricKey)}
* </ul>
*/
@Deprecated
public SecureCell(int mode) {

if (mode < MODE_SEAL || mode > MODE_CONTEXT_IMPRINT) {
Expand All @@ -617,7 +626,11 @@ public SecureCell(int mode) {
/**
* Creates new SecureCell with default master key in SEAL mode
* @param default master key
* @deprecated since JavaThemis 0.13
* <p>
* Use {@link #SealWithKey(byte[])} instead.
*/
@Deprecated
public SecureCell(byte[] key) {
this.key = key;
}
Expand All @@ -627,7 +640,16 @@ public SecureCell(byte[] key) {
* @param default master key
* @param SecureCell mode
* @throws InvalidArgumentException when unsupported mode is specified
* @deprecated since JavaThemis 0.13
* <p>
* Use an appropriate static factory method instead:
* <ul>
* <li>{@link #SealWithKey(byte[])}
* <li>{@link #TokenProtectWithKey(byte[])}
* <li>{@link #ContextImprintWithKey(byte[])}
* </ul>
*/
@Deprecated
public SecureCell(byte[] key, int mode) {
this(mode);
this.key = key;
Expand All @@ -636,7 +658,18 @@ public SecureCell(byte[] key, int mode) {
/**
* Creates new SecureCell with default master password in SEAL mode
* @param default master password
* @deprecated since JavaThemis 0.13
* <p>
* This method is <strong>not secure</strong> when used with short passphrases or passwords.
* Do not use it in new code.
* <p>
* If you need to use short passphrases, consider {@link #SealWithPassphrase(String)}.
* Otherwise consider using symmetric keys: {@link #SealWithKey(SymmetricKey)}.
* <p>
* This method does not have direct counterpart in the new API.
* It is equivalent to {@code SecureCell.SealWithKey(password.getBytes("UTF-16"))}.
*/
@Deprecated
public SecureCell(String password) {
this(password.getBytes(CHARSET));
}
Expand All @@ -646,7 +679,23 @@ public SecureCell(String password) {
* @param default master password
* @param SecureCell mode
* @throws InvalidArgumentException when unsupported mode is specified
* @deprecated since JavaThemis 0.13
* <p>
* This method is <strong>not secure</strong> when used with short passphrases or passwords.
* Do not use it in new code.
* <p>
* If you need to use short passphrases, consider {@link #SealWithPassphrase(String)}.
* Otherwise consider using symmetric keys:
* <ul>
* <li>{@link #SealWithKey(byte[])}
* <li>{@link #TokenProtectWithKey(byte[])}
* <li>{@link #ContextImprintWithKey(byte[])}
* </ul>
* This method does not have direct counterpart in the new API.
* It is equivalent to {@code SecureCell.SealWithKey(password.getBytes("UTF-16"))}
* or corresponding other mode.
*/
@Deprecated
public SecureCell(String password, int mode) {
this(mode);
this.key = password.getBytes(CHARSET);
Expand All @@ -656,9 +705,15 @@ public SecureCell(String password, int mode) {
byte[] key;

static final Charset CHARSET = StandardCharsets.UTF_16;


/** @deprecated since JavaThemis 0.13 */
@Deprecated
public static final int MODE_SEAL = 0;
/** @deprecated since JavaThemis 0.13 */
@Deprecated
public static final int MODE_TOKEN_PROTECT = 1;
/** @deprecated since JavaThemis 0.13 */
@Deprecated
public static final int MODE_CONTEXT_IMPRINT = 2;
static final int MODE_SEAL_PASSPHRASE = 3;

Expand Down Expand Up @@ -734,7 +789,11 @@ static byte[] unprotect(byte[] key, byte[] context, SecureCellData protectedData
* @return SecureCellData with protected data
* @throws NullArgumentException when key or data is null
* @throws SecureCellException when cannot protect the data
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code encrypt(byte[], byte[])} instead.
*/
@Deprecated
public SecureCellData protect(byte[] key, byte[] context, byte[] data) throws SecureCellException {
return protect(key, context, data, this.mode);
}
Expand All @@ -746,7 +805,11 @@ public SecureCellData protect(byte[] key, byte[] context, byte[] data) throws Se
* @return SecureCellData with protected data
* @throws NullArgumentException when default master key or data is null
* @throws SecureCellException when cannot protect the data
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code encrypt(byte[], byte[])} instead.
*/
@Deprecated
public SecureCellData protect(byte[] context, byte[] data) throws SecureCellException {
return this.protect(this.key, context, data);
}
Expand All @@ -759,7 +822,14 @@ public SecureCellData protect(byte[] context, byte[] data) throws SecureCellExce
* @return SecureCellData with protected data
* @throws NullArgumentException when key or data is null
* @throws SecureCellException when cannot protect the data
* @deprecated since JavaThemis 0.13
* <p>
* This method is <strong>not secure</strong> when used with short passphrases or passwords.
* Do not use it in new code.
* <p>
* Consider using new construction API with passphrases instead.
*/
@Deprecated
public SecureCellData protect(String password, String context, byte[] data) throws SecureCellException {
return this.protect(password.getBytes(CHARSET), context.getBytes(CHARSET), data);
}
Expand All @@ -771,7 +841,11 @@ public SecureCellData protect(String password, String context, byte[] data) thro
* @return SecureCellData with protected data
* @throws NullArgumentException when key or data is null
* @throws SecureCellException when cannot protect the data
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code encrypt(byte[], byte[])} instead.
*/
@Deprecated
public SecureCellData protect(String context, byte[] data) throws SecureCellException {
return this.protect(this.key, context.getBytes(CHARSET), data);
}
Expand All @@ -785,7 +859,11 @@ public SecureCellData protect(String context, byte[] data) throws SecureCellExce
* @throws NullArgumentException when key or protectedData is null
* @throws SecureCellException when cannot decrypt protectedData
* @throws InvalidArgumentException when protectedData is incorrect
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code decrypt(byte[], byte[])} instead.
*/
@Deprecated
public byte[] unprotect(byte[] key, byte[] context, SecureCellData protectedData) throws SecureCellException {
return unprotect(key, context, protectedData, this.mode);
}
Expand All @@ -798,7 +876,11 @@ public byte[] unprotect(byte[] key, byte[] context, SecureCellData protectedData
* @throws NullArgumentException when key or protectedData is null
* @throws SecureCellException when cannot decrypt protectedData
* @throws InvalidArgumentException when protectedData is incorrect
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code decrypt(byte[], byte[])} instead.
*/
@Deprecated
public byte[] unprotect(byte[] context, SecureCellData protectedData) throws SecureCellException {
return this.unprotect(this.key, context, protectedData);
}
Expand All @@ -812,7 +894,14 @@ public byte[] unprotect(byte[] context, SecureCellData protectedData) throws Sec
* @throws NullArgumentException when key or protectedData is null
* @throws SecureCellException when cannot decrypt protectedData
* @throws InvalidArgumentException when protectedData is incorrect
* @deprecated since JavaThemis 0.13
* <p>
* This method is <strong>not secure</strong> when used with short passphrases or passwords.
* Do not use it in new code.
* <p>
* Consider using new construction API with passphrases instead.
*/
@Deprecated
public byte[] unprotect(String password, String context, SecureCellData protectedData) throws SecureCellException {
return this.unprotect(password.getBytes(CHARSET), context.getBytes(CHARSET), protectedData);
}
Expand All @@ -825,7 +914,11 @@ public byte[] unprotect(String password, String context, SecureCellData protecte
* @throws NullArgumentException when key or protectedData is null
* @throws SecureCellException when cannot decrypt protectedData
* @throws InvalidArgumentException when protectedData is incorrect
* @deprecated since JavaThemis 0.13
* <p>
* Use new construction API and {@code decrypt(byte[], byte[])} instead.
*/
@Deprecated
public byte[] unprotect(String context, SecureCellData protectedData) throws SecureCellException {
return this.unprotect(this.key, context.getBytes(CHARSET), protectedData);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public byte[] encrypt(byte[] data, byte[] context) {
throw new InvalidArgumentException("context cannot be empty");
}
byte[] keyBytes = this.key.key;
@SuppressWarnings("deprecation")
byte[][] result = SecureCell.encrypt(keyBytes, context, data, SecureCell.MODE_CONTEXT_IMPRINT);
// TODO(ilammy, 2020-05-05): teach SecureCell#encrypt to throw SecureCellException (T1605)
if (result == null) {
Expand All @@ -70,6 +71,7 @@ public byte[] decrypt(byte[] data, byte[] context) {
}
byte[] keyBytes = this.key.key;
byte[][] encrypted = {data, null};
@SuppressWarnings("deprecation")
byte[] result = SecureCell.decrypt(keyBytes, context, encrypted, SecureCell.MODE_CONTEXT_IMPRINT);
// TODO(ilammy, 2020-05-05): teach SecureCell#decrypt to throw SecureCellException (T1605)
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public byte[] encrypt(byte[] data, @Nullable byte[] context) {
throw new InvalidArgumentException("data cannot be empty");
}
byte[] keyBytes = this.key.key;
@SuppressWarnings("deprecation")
byte[][] result = SecureCell.encrypt(keyBytes, context, data, SecureCell.MODE_SEAL);
// TODO(ilammy, 2020-05-05): teach SecureCell#encrypt to throw SecureCellException (T1605)
if (result == null) {
Expand All @@ -65,6 +66,7 @@ public byte[] decrypt(byte[] data, @Nullable byte[] context) throws SecureCellEx
}
byte[] keyBytes = this.key.key;
byte[][] encrypted = {data, null};
@SuppressWarnings("deprecation")
byte[] result = SecureCell.decrypt(keyBytes, context, encrypted, SecureCell.MODE_SEAL);
// TODO(ilammy, 2020-05-05): teach SecureCell#decrypt to throw SecureCellException (T1605)
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public SecureCellData encrypt(byte[] data, @Nullable byte[] context) {
throw new InvalidArgumentException("data cannot be empty");
}
byte[] keyBytes = this.key.key;
@SuppressWarnings("deprecation")
byte[][] result = SecureCell.encrypt(keyBytes, context, data, SecureCell.MODE_TOKEN_PROTECT);
// TODO(ilammy, 2020-05-05): teach SecureCell#encrypt to throw SecureCellException (T1605)
if (result == null) {
Expand Down Expand Up @@ -71,6 +72,7 @@ public byte[] decrypt(byte[] data, byte[] token, @Nullable byte[] context) throw
}
byte[] keyBytes = this.key.key;
byte[][] encrypted = {data, token};
@SuppressWarnings("deprecation")
byte[] result = SecureCell.decrypt(keyBytes, context, encrypted, SecureCell.MODE_TOKEN_PROTECT);
// TODO(ilammy, 2020-05-05): teach SecureCell#encrypt to throw SecureCellException (T1605)
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ public void requiredMessageAndContext() {
}

@Test
@SuppressWarnings("deprecation")
public void oldAPI() throws SecureCellException {
SymmetricKey key = new SymmetricKey();
SecureCell.ContextImprint newCell = SecureCell.ContextImprintWithKey(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ public void emptyMessage() throws SecureCellException {
}

@Test
@SuppressWarnings("deprecation")
public void oldAPI() throws SecureCellException {
SymmetricKey key = new SymmetricKey();
SecureCell.Seal newCell = SecureCell.SealWithKey(key);
Expand All @@ -262,6 +263,7 @@ public void oldAPI() throws SecureCellException {
}

@Test
@SuppressWarnings("deprecation")
public void oldAPIWithoutContext() throws SecureCellException {
SymmetricKey key = new SymmetricKey();
SecureCell.Seal newCell = SecureCell.SealWithKey(key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public void passphraseIsNotSymmetricKey() {
}

@Test
@SuppressWarnings("ResultOfMethodCallIgnored")
@SuppressWarnings({"ResultOfMethodCallIgnored", "deprecation"})
public void passphrasesNotCompatibleWithOldAPI() throws SecureCellException {
// Old 'passphrase-like' API is not passphrase API at all. Don't use it.
SecureCell cellOld = new SecureCell("day 56 of the Q", SecureCell.MODE_SEAL);
Expand All @@ -331,6 +331,7 @@ public void passphrasesNotCompatibleWithOldAPI() throws SecureCellException {
}

@Test
@SuppressWarnings("deprecation")
public void oldPassphraseAPIIsActuallyUTF16Key() throws SecureCellException {
// Yes, it's so weird due to hysterical raisins. So don't use it, really.
SecureCell cellOld = new SecureCell("day 56 of the Q", SecureCell.MODE_SEAL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
import static org.junit.Assert.*;
import org.junit.Test;

/**
* These tests exercise old and deprecated API.
* See {@link SecureCellSealTest}, {@link SecureCellTokenProtectTest},
* {@link SecureCellContextImprintTest} for examples of new API.
*/
@SuppressWarnings("deprecation")
public class SecureCellTest {

static final int MAX_TEST_DATA = 1024;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ public void emptyMessageOrToken() throws SecureCellException {
}

@Test
@SuppressWarnings("deprecation")
public void oldAPI() throws SecureCellException {
SymmetricKey key = new SymmetricKey();
SecureCell.TokenProtect newCell = SecureCell.TokenProtectWithKey(key);
Expand Down Expand Up @@ -441,6 +442,7 @@ public void oldAPI() throws SecureCellException {
}

@Test
@SuppressWarnings("deprecation")
public void oldAPIWithoutContext() throws SecureCellException {
SymmetricKey key = new SymmetricKey();
SecureCell.TokenProtect newCell = SecureCell.TokenProtectWithKey(key);
Expand Down

0 comments on commit 486e214

Please sign in to comment.