From 014245edc7ebec245c5993b238ca83cd6e96d097 Mon Sep 17 00:00:00 2001 From: Joren Schipman Date: Tue, 30 Apr 2024 21:48:00 +0200 Subject: [PATCH] encrypt the initial exchange using rsa --- ConnectNoContext.kt | 86 ++++++++++++++++++++++ public_key.pem | 9 +++ rsaserver.go | 174 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 269 insertions(+) create mode 100644 ConnectNoContext.kt create mode 100644 public_key.pem create mode 100644 rsaserver.go diff --git a/ConnectNoContext.kt b/ConnectNoContext.kt new file mode 100644 index 0000000..956190e --- /dev/null +++ b/ConnectNoContext.kt @@ -0,0 +1,86 @@ +package com.ti.mobpo.ui.util + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import java.io.BufferedReader +import java.io.InputStreamReader +import java.io.PrintWriter +import java.net.Socket +import java.security.SecureRandom +import javax.crypto.Cipher +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.SecretKeySpec + +class Connect { + companion object { + fun decodeBase64(input: String): ByteArray { + return android.util.Base64.decode(input, android.util.Base64.DEFAULT) + } + + fun encodeBase64(input: ByteArray): String { + return android.util.Base64.encodeToString(input, android.util.Base64.DEFAULT) + } + + fun decrypt(algorithm: String, cipherText: String, key: SecretKeySpec, iv: IvParameterSpec): String { + val cipher = Cipher.getInstance(algorithm) + cipher.init(Cipher.DECRYPT_MODE, key, iv) + val plainText = cipher.doFinal(decodeBase64(cipherText)) + return String(plainText) + } + + fun encrypt(algorithm: String, inputText: String, key: SecretKeySpec, iv: IvParameterSpec): String { + val cipher = Cipher.getInstance(algorithm) + cipher.init(Cipher.ENCRYPT_MODE, key, iv) + val cipherText = cipher.doFinal(inputText.toByteArray()) + return encodeBase64(cipherText) + } + + fun main() { + val host = "192.168.90.151" + val port = 8080 + val secureRandom = SecureRandom() + val keyBytes = ByteArray(16) + val ivBytes = ByteArray(16) + secureRandom.nextBytes(keyBytes) + secureRandom.nextBytes(ivBytes) + val key = SecretKeySpec(keyBytes, "AES") + val iv = IvParameterSpec(ivBytes) + val algorithm = "AES/CBC/PKCS5Padding" + + var sendData = "Hello, World!" + + val chunkSize = 45 + val chunks = sendData.chunked(chunkSize) + + val socket = Socket(host, port) + val writer = PrintWriter(socket.getOutputStream(), true) + val reader = BufferedReader(InputStreamReader(socket.getInputStream())) + + val encodedKey = encodeBase64(keyBytes) + writer.println(encodedKey) + reader.readLine() + val encodedIV = encodeBase64(ivBytes) + writer.println(encodedIV) + reader.readLine() + + for (chunk in chunks) { + val cipherText = encrypt(algorithm, chunk, key, iv) + writer.println(cipherText) + reader.readLine() + } + + writer.println("END_OF_COMMUNICATION") + reader.readLine() + + println("Client: Ready for next operation") + writer.println("Ready for next operation") + reader.readLine() + + + writer.close() + reader.close() + socket.close() + } + } +} + diff --git a/public_key.pem b/public_key.pem new file mode 100644 index 0000000..af95d51 --- /dev/null +++ b/public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu09x4q24cMSJZmxMGSzR +oL3jXG3kguVbBV6zRnPZwPT9nIofs7yb4lh6/deNedNJssLYJEmiAyI3NzsvLzih +ipCjatAYEgLgRcF60HBrqUKwT6uxukoVbXi+c9O70CjDEJEKDSW/ps5d6cAOMq5K +moGe4f+Geo5Nzxwjdhlaw/wjY1r5S/C7c5JRMSTn5xYwRZJFM4zRSOEz8d02FemL +LWQggvRV7bIJuk1w0039sO/RjWTOeMqNPXXaBH6jV6seDCJ4coXWv0g4xNwCrxNt +m1aRFW3zyh3GhAEVXcOmJ5EOUL6EiKt+5RTtSdL7OKHv+RfQuv4pkmlqpPo8pQHv +nQIDAQAB +-----END PUBLIC KEY----- diff --git a/rsaserver.go b/rsaserver.go new file mode 100644 index 0000000..1de130d --- /dev/null +++ b/rsaserver.go @@ -0,0 +1,174 @@ +package main + +import ( + "bufio" + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "strings" + "fmt" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "io/ioutil" + "log" + "net" +) + +func main() { + host := "0.0.0.0" + port := 8080 + + privateKeyPath := "private_key.pem" + + // Load the private key from the PEM file + + privateKey, err := loadPrivateKeyFromPEM(privateKeyPath) + if err != nil { + fmt.Println("Error loading private key:", err) + return + } + listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) + if err != nil { + log.Fatalf("Error listening: %v", err) + } + defer listener.Close() + + fmt.Printf("Server listening on %s:%d\n", host, port) + + for { + conn, err := listener.Accept() + if err != nil { + log.Printf("Error accepting connection: %v", err) + continue + } + + go handleConnection(conn, privateKey) + } +} + +func handleConnection(conn net.Conn, privateKey *rsa.PrivateKey) { + defer conn.Close() + + fmt.Println("Got conn") + + keyData, err := bufio.NewReader(conn).ReadString('\n') + if err != nil { + log.Printf("Error reading key: %v", err) + return + } + + key, _ := decryptKeyIV(keyData, privateKey) + conn.Write([]byte("Received key\n")) + + ivData, _ := bufio.NewReader(conn).ReadString('\n') + iv, _ := decryptKeyIV(ivData,privateKey) + conn.Write([]byte("Received IV\n")) + + var ciphertext []byte + var chunk string + var plaintext []byte + + for { + chunk, err = bufio.NewReader(conn).ReadString('\n') + if err != nil { + log.Printf("Error reading chunk: %v", err) + return + } + if strings.TrimSpace(chunk) == "END_OF_COMMUNICATION" { + fmt.Println("Client ended communication") + break + } + ciphertext, _ = base64.StdEncoding.DecodeString(strings.TrimSpace(chunk)) + + plaintextChunk, err := decrypt(ciphertext, key, iv) + if err != nil { + log.Printf("Error decrypting chunk: %v", err) + return + } + plaintext = append(plaintext, plaintextChunk...) + + conn.Write([]byte("Received and decrypted chunk\n")) + } + + fmt.Println("Decrypted text:", string(plaintext)) + conn.Write([]byte("Ready for next operation\n")) +} + + + + +func decrypt(cipherText []byte, key []byte, iv []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + if len(cipherText) < aes.BlockSize { + return nil, fmt.Errorf("ciphertext too short") + } + + mode := cipher.NewCBCDecrypter(block, iv) + mode.CryptBlocks(cipherText, cipherText) + + cipherText = PKCS5Unpadding(cipherText) + + return cipherText, nil +} + +func PKCS5Unpadding(data []byte) []byte { + length := len(data) + unpadding := int(data[length-1]) + return data[:(length - unpadding)] +} + +func decryptRSA(encryptedData []byte, privateKey *rsa.PrivateKey) ([]byte, error) { + decryptedData, err := rsa.DecryptPKCS1v15(nil, privateKey, encryptedData) + if err != nil { + return nil, err + } + return decryptedData, nil +} + +func loadPrivateKeyFromPEM(filePath string) (*rsa.PrivateKey, error) { + // Read the PEM file + pemData, err := ioutil.ReadFile(filePath) + if err != nil { + return nil, err + } + + // Decode PEM data + block, _ := pem.Decode(pemData) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM data") + } + + // Parse the key + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + + // Assert that the key is an RSA private key + rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey) + if !ok { + return nil, fmt.Errorf("not an RSA private key") + } + + return rsaPrivateKey, nil +} + +func decryptKeyIV(ed string, privateKey *rsa.PrivateKey) ([]byte, error) { + encryptedData, err := base64.StdEncoding.DecodeString(ed) + if err != nil { + return nil, err + } + + decryptedMessage, err := decryptRSA(encryptedData, privateKey) + if err != nil { + fmt.Println("Error decrypting message:", err) + return nil, err + } + decodedKey, _ := base64.StdEncoding.DecodeString(strings.TrimSpace(string(decryptedMessage))) + return decodedKey, err +} \ No newline at end of file