Need help converting Java encryption example to Elixir

Im writing an integration in Elixir and as one part I need to create an encrypted login string. However I have zero experience with encryption and im not able to understand the Erlang docs well enogh to understand. I would rather use pure Erlang to do this that add some dependency to a Elexir wrapper if possible.

The Java code I need to write in Elixir looks as follows.

  private String encryptAuthParameter(String user, String password)
      throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, NoSuchPaddingException,
          InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    // Construct the base for the auth parameter
    String login =
        Base64.getEncoder().encodeToString(user.getBytes())
            + ":"
            + Base64.getEncoder().encodeToString(password.getBytes())
            + ":"
            + Base64.getEncoder()
                .encodeToString(String.valueOf(System.currentTimeMillis()).getBytes());

    // RSA encrypt it using NNAPI public key
    PublicKey pubKey = getKeyFromPEM(Main.PUBLIC_KEY_FILENAME);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);

    byte[] encryptedBytes = cipher.doFinal(login.getBytes("UTF-8"));

    // Encode the encrypted data in Base64
    String encodedEncryptedBytes = Base64.getEncoder().encodeToString(encryptedBytes);

    return URLEncoder.encode(encodedEncryptedBytes, "UTF-8");
  }

  private static PublicKey getKeyFromPEM(String filename)
      throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
    BufferedReader reader = null;
    try {
      reader = new BufferedReader(new FileReader(filename));
      String line = null;
      String key = "";
      while (true) {
        line = reader.readLine();
        if (line == null) break;
        else if (line.startsWith("-----BEGIN PUBLIC KEY-----")) continue;
        else if (line.startsWith("-----END PUBLIC KEY-----")) continue;
        else key += line.trim();
      }
      byte[] binary = Base64.getDecoder().decode(key);
      X509EncodedKeySpec spec = new X509EncodedKeySpec(binary);
      KeyFactory kf = KeyFactory.getInstance("RSA");
      return kf.generatePublic(spec);
    } finally {
      if (reader != null) {
        reader.close();
      }
    }
  }

The only thing I have so far is:

  def encryptAuthParameter(user, password) do
    now = DateTime.utc_now() |> DateTime.to_unix(:millisecond) |> Integer.to_string()
    # Convert to Base64
    login = Base.encode64(user) <> ":" <> Base.encode64(password) <> ":" <> Base.encode64(now)
    # Use public key to encode message
    File.read!()
    # Base 64 encode the encrypted string
    login
  end

Turns out it was not that hard. Here is the code that got it working.

  def encryptAuthParameter(user, password) do
    # Convert to Base64
    now_str = DateTime.utc_now() |> DateTime.to_unix(:millisecond) |> Integer.to_string()
    login_msg = Base.encode64(user) <> ":" <> Base.encode64(password) <> ":" <> Base.encode64(now_str)
    # Use public key to encode message
    raw_p_key = getKeyFromPEM(@key)
    [enc_p_key] = :public_key.pem_decode(raw_p_key)
    p_key = :public_key.pem_entry_decode(enc_p_key)
    enc_msg = :public_key.encrypt_public(login_msg, p_key)
    # Base 64 encode the encrypted string
    Base.encode64(enc_msg)
  end

  def getKeyFromPEM(filename) do
    File.read!(filename)
  end
1 Like