Convert CipherState to Kotlin

This commit is contained in:
yet 2026-05-15 17:36:07 +04:00
parent ec60cb3543
commit e8882d6ab1
2 changed files with 146 additions and 129 deletions

View File

@ -19,144 +19,161 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package com.bitchat.android.noise.southernstorm.protocol
package com.bitchat.android.noise.southernstorm.protocol;
import javax.crypto.BadPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.BadPaddingException
import javax.crypto.ShortBufferException
/**
* Interface to an authenticated cipher for use in the Noise protocol.
*
*
* CipherState objects are used to encrypt or decrypt data during a
* session. Once the handshake has completed, HandshakeState.split()
* will create two CipherState objects for encrypting packets sent to
* the other party, and decrypting packets received from the other party.
*/
public interface CipherState extends Destroyable {
interface CipherState : Destroyable {
/**
* Gets the Noise protocol name for this cipher.
*
* @return The cipher name.
*/
val cipherName: String
/**
* Gets the Noise protocol name for this cipher.
*
* @return The cipher name.
*/
String getCipherName();
/**
* Gets the length of the key values for this cipher.
*
* @return The length of the key in bytes; usually 32.
*/
val keyLength: Int
/**
* Gets the length of the key values for this cipher.
*
* @return The length of the key in bytes; usually 32.
*/
int getKeyLength();
/**
* Gets the length of the MAC values for this cipher.
*
* @return The length of MAC values in bytes, or zero if the
* key has not yet been initialized.
*/
int getMACLength();
/**
* Gets the length of the MAC values for this cipher.
*
* @return The length of MAC values in bytes, or zero if the
* key has not yet been initialized.
*/
// JvmName preserved so existing Java impls/callers (getMACLength) keep
// resolving — Kotlin would otherwise expose this as getMacLength.
@get:JvmName("getMACLength")
val macLength: Int
/**
* Initializes the key on this cipher object.
*
* @param key Points to a buffer that contains the key.
* @param offset The offset of the key in the key buffer.
*
* The key buffer must contain at least getKeyLength() bytes
* starting at offset.
*
* @see #hasKey()
*/
void initializeKey(byte[] key, int offset);
/**
* Initializes the key on this cipher object.
*
* @param key Points to a buffer that contains the key.
* @param offset The offset of the key in the key buffer.
*
* The key buffer must contain at least getKeyLength() bytes
* starting at offset.
*
* @see .hasKey
*/
fun initializeKey(key: ByteArray, offset: Int)
/**
* Determine if this cipher object has been configured with a key.
*
* @return true if this cipher object has a key; false if the
* key has not yet been set with initializeKey().
*
* @see #initializeKey(byte[], int)
*/
boolean hasKey();
/**
* Encrypts a plaintext buffer using the cipher and a block of associated data.
*
* @param ad The associated data, or null if there is none.
* @param plaintext The buffer containing the plaintext to encrypt.
* @param plaintextOffset The offset within the plaintext buffer of the
* first byte or plaintext data.
* @param ciphertext The buffer to place the ciphertext in. This can
* be the same as the plaintext buffer.
* @param ciphertextOffset The first offset within the ciphertext buffer
* to place the ciphertext and the MAC tag.
* @param length The length of the plaintext.
* @return The length of the ciphertext plus the MAC tag, or -1 if the
* ciphertext buffer is not large enough to hold the result.
*
* @throws ShortBufferException The ciphertext buffer does not have
* enough space to hold the ciphertext plus MAC.
*
* @throws IllegalStateException The nonce has wrapped around.
*
* @throws IllegalArgumentException One of the parameters is out of range.
*
* The plaintext and ciphertext buffers can be the same for in-place
* encryption. In that case, plaintextOffset must be identical to
* ciphertextOffset.
*
* There must be enough space in the ciphertext buffer to accomodate
* length + getMACLength() bytes of data starting at ciphertextOffset.
*/
int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset, byte[] ciphertext, int ciphertextOffset, int length) throws ShortBufferException;
/**
* Determine if this cipher object has been configured with a key.
*
* @return true if this cipher object has a key; false if the
* key has not yet been set with initializeKey().
*
* @see .initializeKey
*/
fun hasKey(): Boolean
/**
* Decrypts a ciphertext buffer using the cipher and a block of associated data.
*
* @param ad The associated data, or null if there is none.
* @param ciphertext The buffer containing the ciphertext to decrypt.
* @param ciphertextOffset The offset within the ciphertext buffer of
* the first byte of ciphertext data.
* @param plaintext The buffer to place the plaintext in. This can be
* the same as the ciphertext buffer.
* @param plaintextOffset The first offset within the plaintext buffer
* to place the plaintext.
* @param length The length of the incoming ciphertext plus the MAC tag.
* @return The length of the plaintext with the MAC tag stripped off.
*
* @throws ShortBufferException The plaintext buffer does not have
* enough space to store the decrypted data.
*
* @throws BadPaddingException The MAC value failed to verify.
*
* @throws IllegalStateException The nonce has wrapped around.
*
* @throws IllegalArgumentException One of the parameters is out of range.
*
* The plaintext and ciphertext buffers can be the same for in-place
* decryption. In that case, ciphertextOffset must be identical to
* plaintextOffset.
*/
int decryptWithAd(byte[] ad, byte[] ciphertext, int ciphertextOffset, byte[] plaintext, int plaintextOffset, int length) throws ShortBufferException, BadPaddingException;
/**
* Encrypts a plaintext buffer using the cipher and a block of associated data.
*
* @param ad The associated data, or null if there is none.
* @param plaintext The buffer containing the plaintext to encrypt.
* @param plaintextOffset The offset within the plaintext buffer of the
* first byte or plaintext data.
* @param ciphertext The buffer to place the ciphertext in. This can
* be the same as the plaintext buffer.
* @param ciphertextOffset The first offset within the ciphertext buffer
* to place the ciphertext and the MAC tag.
* @param length The length of the plaintext.
* @return The length of the ciphertext plus the MAC tag, or -1 if the
* ciphertext buffer is not large enough to hold the result.
*
* @throws ShortBufferException The ciphertext buffer does not have
* enough space to hold the ciphertext plus MAC.
*
* @throws IllegalStateException The nonce has wrapped around.
*
* @throws IllegalArgumentException One of the parameters is out of range.
*
* The plaintext and ciphertext buffers can be the same for in-place
* encryption. In that case, plaintextOffset must be identical to
* ciphertextOffset.
*
* There must be enough space in the ciphertext buffer to accomodate
* length + getMACLength() bytes of data starting at ciphertextOffset.
*/
@Throws(ShortBufferException::class)
fun encryptWithAd(
ad: ByteArray?,
plaintext: ByteArray,
plaintextOffset: Int,
ciphertext: ByteArray,
ciphertextOffset: Int,
length: Int
): Int
/**
* Creates a new instance of this cipher and initializes it with a key.
*
* @param key The buffer containing the key.
* @param offset The offset into the key buffer of the first key byte.
* @return A new CipherState of the same class as this one.
*/
CipherState fork(byte[] key, int offset);
/**
* Sets the nonce value.
*
* @param nonce The new nonce value, which must be greater than or equal
* to the current value.
*
* This function is intended for testing purposes only. If the nonce
* value goes backwards then security may be compromised.
*/
void setNonce(long nonce);
/**
* Decrypts a ciphertext buffer using the cipher and a block of associated data.
*
* @param ad The associated data, or null if there is none.
* @param ciphertext The buffer containing the ciphertext to decrypt.
* @param ciphertextOffset The offset within the ciphertext buffer of
* the first byte of ciphertext data.
* @param plaintext The buffer to place the plaintext in. This can be
* the same as the ciphertext buffer.
* @param plaintextOffset The first offset within the plaintext buffer
* to place the plaintext.
* @param length The length of the incoming ciphertext plus the MAC tag.
* @return The length of the plaintext with the MAC tag stripped off.
*
* @throws ShortBufferException The plaintext buffer does not have
* enough space to store the decrypted data.
*
* @throws BadPaddingException The MAC value failed to verify.
*
* @throws IllegalStateException The nonce has wrapped around.
*
* @throws IllegalArgumentException One of the parameters is out of range.
*
* The plaintext and ciphertext buffers can be the same for in-place
* decryption. In that case, ciphertextOffset must be identical to
* plaintextOffset.
*/
@Throws(ShortBufferException::class, BadPaddingException::class)
fun decryptWithAd(
ad: ByteArray?,
ciphertext: ByteArray,
ciphertextOffset: Int,
plaintext: ByteArray,
plaintextOffset: Int,
length: Int
): Int
/**
* Creates a new instance of this cipher and initializes it with a key.
*
* @param key The buffer containing the key.
* @param offset The offset into the key buffer of the first key byte.
* @return A new CipherState of the same class as this one.
*/
fun fork(key: ByteArray, offset: Int): CipherState
/**
* Sets the nonce value.
*
* @param nonce The new nonce value, which must be greater than or equal
* to the current value.
*
* This function is intended for testing purposes only. If the nonce
* value goes backwards then security may be compromised.
*/
fun setNonce(nonce: Long)
}

View File

@ -122,7 +122,7 @@ class SymmetricState implements Destroyable {
*/
public int getMACLength()
{
return cipher.getMACLength();
return cipher.mACLength;
}
/**
@ -142,7 +142,7 @@ class SymmetricState implements Destroyable {
Log.d(TAG, "Current CK: " + bytesToHex(ck));
Log.d(TAG, "Current Hash: " + bytesToHex(h));
int keyLength = cipher.getKeyLength();
int keyLength = cipher.keyLength;
byte[] tempKey = new byte [keyLength];
try {
hkdf(ck, 0, ck.length, data, offset, length, ck, 0, ck.length, tempKey, 0, keyLength);
@ -155,7 +155,7 @@ class SymmetricState implements Destroyable {
Log.d(TAG, "*** Android mixKey() AFTER ***");
Log.d(TAG, "New CK: " + bytesToHex(ck));
Log.d(TAG, "Hash unchanged: " + bytesToHex(h));
Log.d(TAG, "Cipher now has key: " + (cipher.getMACLength() > 0));
Log.d(TAG, "Cipher now has key: " + (cipher.mACLength > 0));
}
/**
@ -314,7 +314,7 @@ class SymmetricState implements Destroyable {
{
if (length != 0 && length != 32)
throw new IllegalArgumentException("Secondary keys must be 0 or 32 bytes in length");
int keyLength = cipher.getKeyLength();
int keyLength = cipher.keyLength;
byte[] k1 = new byte [keyLength];
byte[] k2 = new byte [keyLength];
try {