remove trash

This commit is contained in:
callebtc
2025-07-19 15:56:16 +02:00
parent 6b853a253c
commit a19b4dc991
@@ -1,361 +0,0 @@
package com.bitchat.android.noise.protocol
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.ChaCha20ParameterSpec
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec as HmacKeySpec
import java.nio.ByteBuffer
import java.nio.ByteOrder
/**
* Local fork of Noise Protocol Framework that PROPERLY supports setting pre-existing keys
* This fixes the critical limitation in noise-java where setPrivateKey() doesn't work
* Implements the complete Noise_XX_25519_ChaChaPoly_SHA256 protocol
*/
/**
* Exception thrown by Noise protocol operations
*/
class NoiseException(message: String, cause: Throwable? = null) : Exception(message, cause)
/**
* DH (Diffie-Hellman) interface for key exchange operations
*/
interface DHState {
fun dhName(): String
fun hasPrivateKey(): Boolean
fun hasPublicKey(): Boolean
fun privateKeyLength(): Int
fun publicKeyLength(): Int
fun generateKeyPair()
fun setPrivateKey(privateKey: ByteArray, offset: Int)
fun setPublicKey(publicKey: ByteArray, offset: Int)
fun getPrivateKey(privateKey: ByteArray, offset: Int)
fun getPublicKey(publicKey: ByteArray, offset: Int)
fun performDH(otherPublicKey: ByteArray, sharedSecret: ByteArray)
fun destroy()
}
/**
* Cipher interface for symmetric encryption/decryption
*/
interface CipherState {
fun cipherName(): String
fun hasKey(): Boolean
fun keyLength(): Int
fun initializeKey(key: ByteArray, offset: Int)
fun encryptWithAd(
associatedData: ByteArray?,
plaintext: ByteArray,
plaintextOffset: Int,
ciphertext: ByteArray,
ciphertextOffset: Int,
length: Int
): Int
fun decryptWithAd(
associatedData: ByteArray?,
ciphertext: ByteArray,
ciphertextOffset: Int,
plaintext: ByteArray,
plaintextOffset: Int,
length: Int
): Int
fun fork(): CipherState
fun destroy()
}
/**
* Hash interface for cryptographic hashing
*/
interface HashState {
fun hashName(): String
fun hashLength(): Int
fun blockLength(): Int
fun reset()
fun update(data: ByteArray, offset: Int, length: Int)
fun digest(output: ByteArray, offset: Int)
fun fork(): HashState
}
/**
* Curve25519 implementation with PROPER key setting support
*/
class Curve25519DHState : DHState {
private var privateKeyBytes: ByteArray? = null
private var publicKeyBytes: ByteArray? = null
override fun dhName() = "25519"
override fun hasPrivateKey() = privateKeyBytes != null
override fun hasPublicKey() = publicKeyBytes != null
override fun privateKeyLength() = 32
override fun publicKeyLength() = 32
override fun generateKeyPair() {
val random = SecureRandom()
privateKeyBytes = ByteArray(32)
random.nextBytes(privateKeyBytes!!)
// Clamp private key for Curve25519
privateKeyBytes!![0] = (privateKeyBytes!![0].toInt() and 248).toByte()
privateKeyBytes!![31] = (privateKeyBytes!![31].toInt() and 127).toByte()
privateKeyBytes!![31] = (privateKeyBytes!![31].toInt() or 64).toByte()
// Calculate public key
publicKeyBytes = curve25519ScalarMult(privateKeyBytes!!, curve25519BasePoint())
}
override fun setPrivateKey(privateKey: ByteArray, offset: Int) {
require(privateKey.size - offset >= 32) { "Private key must be 32 bytes" }
privateKeyBytes = privateKey.copyOfRange(offset, offset + 32)
}
override fun setPublicKey(publicKey: ByteArray, offset: Int) {
require(publicKey.size - offset >= 32) { "Public key must be 32 bytes" }
publicKeyBytes = publicKey.copyOfRange(offset, offset + 32)
}
override fun getPrivateKey(privateKey: ByteArray, offset: Int) {
val key = privateKeyBytes ?: throw NoiseException("No private key available")
require(privateKey.size - offset >= 32) { "Output buffer too small" }
key.copyInto(privateKey, offset)
}
override fun getPublicKey(publicKey: ByteArray, offset: Int) {
val key = publicKeyBytes ?: throw NoiseException("No public key available")
require(publicKey.size - offset >= 32) { "Output buffer too small" }
key.copyInto(publicKey, offset)
}
override fun performDH(otherPublicKey: ByteArray, sharedSecret: ByteArray) {
val privateKey = privateKeyBytes ?: throw NoiseException("No private key available")
require(otherPublicKey.size >= 32) { "Other public key must be 32 bytes" }
require(sharedSecret.size >= 32) { "Shared secret buffer must be 32 bytes" }
val shared = curve25519ScalarMult(privateKey, otherPublicKey)
shared.copyInto(sharedSecret, 0)
}
override fun destroy() {
privateKeyBytes?.fill(0)
publicKeyBytes?.fill(0)
privateKeyBytes = null
publicKeyBytes = null
}
// Curve25519 scalar multiplication (simplified - in production use a proper crypto library)
private fun curve25519ScalarMult(scalar: ByteArray, point: ByteArray): ByteArray {
// This is a simplified implementation
// In production, use a proper Curve25519 implementation
// For testing purposes, we'll use a mock that maintains the interface
val result = ByteArray(32)
// Simple XOR-based mock (NOT CRYPTOGRAPHICALLY SECURE - FOR TESTING ONLY)
for (i in 0 until 32) {
result[i] = (scalar[i].toInt() xor point[i].toInt()).toByte()
}
return result
}
private fun curve25519BasePoint(): ByteArray {
val basePoint = ByteArray(32)
basePoint[0] = 9
return basePoint
}
}
/**
* ChaCha20-Poly1305 cipher implementation
*/
class ChaChaPoly1305CipherState : CipherState {
private var key: ByteArray? = null
private var nonce: Long = 0
override fun cipherName() = "ChaChaPoly"
override fun hasKey() = key != null
override fun keyLength() = 32
override fun initializeKey(key: ByteArray, offset: Int) {
require(key.size - offset >= 32) { "Key must be 32 bytes" }
this.key = key.copyOfRange(offset, offset + 32)
this.nonce = 0
}
override fun encryptWithAd(
associatedData: ByteArray?,
plaintext: ByteArray,
plaintextOffset: Int,
ciphertext: ByteArray,
ciphertextOffset: Int,
length: Int
): Int {
val key = this.key ?: throw NoiseException("Cipher not initialized")
// Create 12-byte nonce (4 bytes zero + 8 bytes counter)
val nonceBytes = ByteArray(12)
ByteBuffer.wrap(nonceBytes, 4, 8).order(ByteOrder.LITTLE_ENDIAN).putLong(nonce)
try {
// Use ChaCha20 cipher
val chacha20 = Cipher.getInstance("ChaCha20")
val keySpec = SecretKeySpec(key, "ChaCha20")
val paramSpec = ChaCha20ParameterSpec(nonceBytes, 1)
chacha20.init(Cipher.ENCRYPT_MODE, keySpec, paramSpec)
// Encrypt
val encrypted = chacha20.doFinal(plaintext, plaintextOffset, length)
// Add Poly1305 MAC (simplified - compute HMAC as substitute)
val mac = Mac.getInstance("HmacSHA256")
val macKey = HmacKeySpec(key, "HmacSHA256")
mac.init(macKey)
if (associatedData != null) {
mac.update(associatedData)
}
mac.update(encrypted)
val tag = mac.doFinal().copyOf(16) // Truncate to 16 bytes
// Copy encrypted data and tag to output
encrypted.copyInto(ciphertext, ciphertextOffset)
tag.copyInto(ciphertext, ciphertextOffset + length)
nonce++
return length + 16 // plaintext length + 16 byte tag
} catch (e: Exception) {
throw NoiseException("Encryption failed", e)
}
}
override fun decryptWithAd(
associatedData: ByteArray?,
ciphertext: ByteArray,
ciphertextOffset: Int,
plaintext: ByteArray,
plaintextOffset: Int,
length: Int
): Int {
val key = this.key ?: throw NoiseException("Cipher not initialized")
require(length >= 16) { "Ciphertext too short for tag" }
val plaintextLength = length - 16
val encryptedData = ciphertext.copyOfRange(ciphertextOffset, ciphertextOffset + plaintextLength)
val receivedTag = ciphertext.copyOfRange(ciphertextOffset + plaintextLength, ciphertextOffset + length)
// Create 12-byte nonce (4 bytes zero + 8 bytes counter)
val nonceBytes = ByteArray(12)
ByteBuffer.wrap(nonceBytes, 4, 8).order(ByteOrder.LITTLE_ENDIAN).putLong(nonce)
try {
// Verify MAC first
val mac = Mac.getInstance("HmacSHA256")
val macKey = HmacKeySpec(key, "HmacSHA256")
mac.init(macKey)
if (associatedData != null) {
mac.update(associatedData)
}
mac.update(encryptedData)
val expectedTag = mac.doFinal().copyOf(16)
if (!receivedTag.contentEquals(expectedTag)) {
throw NoiseException("Authentication failed")
}
// Decrypt
val chacha20 = Cipher.getInstance("ChaCha20")
val keySpec = SecretKeySpec(key, "ChaCha20")
val paramSpec = ChaCha20ParameterSpec(nonceBytes, 1)
chacha20.init(Cipher.DECRYPT_MODE, keySpec, paramSpec)
val decrypted = chacha20.doFinal(encryptedData)
decrypted.copyInto(plaintext, plaintextOffset)
nonce++
return plaintextLength
} catch (e: Exception) {
throw NoiseException("Decryption failed", e)
}
}
override fun fork(): CipherState {
val forked = ChaChaPoly1305CipherState()
key?.let { forked.initializeKey(it, 0) }
return forked
}
override fun destroy() {
key?.fill(0)
key = null
nonce = 0
}
}
/**
* SHA-256 hash implementation
*/
class SHA256HashState : HashState {
private var messageDigest = java.security.MessageDigest.getInstance("SHA-256")
override fun hashName() = "SHA256"
override fun hashLength() = 32
override fun blockLength() = 64
override fun reset() {
messageDigest.reset()
}
override fun update(data: ByteArray, offset: Int, length: Int) {
messageDigest.update(data, offset, length)
}
override fun digest(output: ByteArray, offset: Int) {
val hash = messageDigest.digest()
hash.copyInto(output, offset)
}
override fun fork(): HashState {
val forked = SHA256HashState()
// Note: Java MessageDigest doesn't support cloning directly
// For a complete implementation, we'd need to track state manually
return forked
}
}
/**
* Factory for creating crypto primitives
*/
object NoiseFactory {
fun createDH(name: String): DHState {
return when (name) {
"25519" -> Curve25519DHState()
else -> throw NoiseException("Unsupported DH algorithm: $name")
}
}
fun createCipher(name: String): CipherState {
return when (name) {
"ChaChaPoly" -> ChaChaPoly1305CipherState()
else -> throw NoiseException("Unsupported cipher: $name")
}
}
fun createHash(name: String): HashState {
return when (name) {
"SHA256" -> SHA256HashState()
else -> throw NoiseException("Unsupported hash: $name")
}
}
}