Non-encrypted confidential information - Hexadecimal - Scala

Non-encrypted confidential information - Hexadecimal - Scala

Need

Secure encryption of confidential information

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play.api.mvc for handling HTTP requests and responses in the Play Framework
  • Usage of global execution context for concurrent programming in Scala

Description

Non compliant code

        import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  def index() = Action { implicit request: Request[AnyContent] =>
    val confidentialData = "Confidential Information"
    val hexData = confidentialData.getBytes("UTF-8").map("%02x".format(_)).mkString
    Ok(hexData)
  }
}
        
        

In the above Scala code, we are using the Play Framework to create a simple web application. The application has a single endpoint, the index, that when accessed, returns some confidential data encoded in hexadecimal.

The HomeController class has a method index(), which is an Action that gets executed when a GET request is made to the root URL ("/") of the application.

Inside this method, we first define a string confidentialData that contains some confidential information. This data is then converted to a byte array using the getBytes("UTF-8") method, which is then mapped to a hexadecimal representation using the map("%02x".format(_)).mkString method.

The problem lies in the fact that this hexadecimal data is then directly sent to the client as a response using Ok(hexData). This means that the confidential data is being sent over the network in a non-encrypted form. Even though it is in hexadecimal form, it can easily be decoded back to plain text, potentially exposing the confidential data to any attacker who might be eavesdropping on the network traffic.

This is a serious security vulnerability as it can lead to the disclosure of sensitive information. It is, therefore, crucial to always encrypt confidential data before sending it over the network.

Steps

  • Use encryption to protect the confidential information instead of encoding it in hexadecimal.
  • Choose a strong encryption algorithm and ensure it is properly implemented.
  • Generate a secure encryption key and keep it confidential.
  • Encrypt the confidential information using the encryption algorithm and key.
  • Store the encrypted information securely, such as in a secure database or file system.
  • When needed, decrypt the encrypted information using the encryption algorithm and key.
  • Ensure that only authorized users or systems have access to the decrypted information.

Compliant code

        import play.api.mvc._
import scala.concurrent.ExecutionContext.Implicits.global
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
import java.util.Base64

class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController {

  private val encryptionKey = "1234567890123456" // This should be stored securely and not hardcoded
  private val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
  private val secretKey = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES")

  def index() = Action { implicit request: Request[AnyContent] =>
    val confidentialData = "Confidential Information"
    cipher.init(Cipher.ENCRYPT_MODE, secretKey)
    val encryptedData = cipher.doFinal(confidentialData.getBytes("UTF-8"))
    val base64EncryptedData = Base64.getEncoder.encodeToString(encryptedData)
    Ok(base64EncryptedData)
  }
}
        
        

The original code was vulnerable because it was encoding confidential information in hexadecimal, which can be easily decoded to plain text. The fixed code uses AES encryption to protect the confidential information.

The encryption key is used to initialize a SecretKeySpec, which is then used to initialize a Cipher for AES encryption. The confidential information is encrypted using the Cipher and the result is encoded in Base64 to ensure it can be safely transmitted or stored.

The encryption key is currently hardcoded for simplicity, but in a real application, it should be securely stored and retrieved, such as from a secure key vault.

The encrypted information can be decrypted using the same AES encryption algorithm and key. Only authorized users or systems should have access to the encryption key to ensure the confidentiality of the information.

Please note that this is a basic example of encryption and may not be suitable for all use cases. For high-security applications, consider using additional security measures such as a more secure mode of operation for the cipher (e.g., CBC or GCM instead of ECB), padding, and a key derivation function.

References