1

I have a python code for generating rsa signatures and I am trying to write this code in elixir. python code:

import sys
import base64
import datetime
import json
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA512


def generate_signature(key_id, private_key_content):
    private_key = RSA.import_key(base64.b64decode(private_key_content))

    timestamp = "2024-12-19T08:48:29.528457+00:00"
    message_to_sign = key_id + timestamp
    print("Message to sign:", message_to_sign)

    hash_obj = SHA512.new(message_to_sign.encode())
    signer = pkcs1_15.new(private_key)
    signature_bytes = signer.sign(hash_obj)
    signature_value = base64.b64encode(signature_bytes).decode()

    return json.dumps({
        "keyId": key_id,
        "timestamp": timestamp,
        "signature": signature_value
    }, indent=2)


def main():
    if len(sys.argv) < 3:
        print("required keyId and privateKey")
    else:
        key_id = sys.argv[1]
        private_key_content = sys.argv[2]
        print(generate_signature(key_id, private_key_content))


if __name__ == "__main__":
    main()

my elixir code:

defmodule RsaExample do
  require Logger

  defp api_key() do
    Application.get_env(:rsa_example, :api_key)
  end

  defp key_id() do
    Application.get_env(:rsa_example, :key_id)
  end

  def get_signature do
    dt = "2024-12-19T08:48:29.528457+00:00"

    message =
      :crypto.hash(:sha512, key_id() <> dt)
      |> Base.encode16()
      |> String.downcase()

    api_key = Base.decode64!(api_key())
    <<_::binary-size(26), der::binary>> = api_key

    key = :public_key.der_decode(:RSAPrivateKey, der)
    signature = :public_key.sign(message, :sha, key) |> Base.encode64()

    {:ok,
      %{
        keyId: key_id(),
        timestamp: dt,
        signature: signature
      }}
  end
end

I tested with these params:

private key:

MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4CuxG1G1KiXFWpLXAGWI0ATKRP+Ixto9ElVqpFsPRB14Cu0TaRA6rEMW2C8LgafUYAJdrfzypB1tlfPpRH1fpQoFNkbYnec5/DJGMrh4fWkSZEflrOcSnY0CEHVG2fO0AMT4toVmgj6svfBSMf6S2sm2rjhQjMSqj87wOG3TNaIvQSaAz7UXa+hzaI7LQ0a41iUUDI6JLYH1EbvjZQQhwjgWlqy5LSeosBXtpPyfLaQDfUaV8eAB5mCt6uV5NlCGKMpvT+h9ZvT8gRn9P9PQeCScFyNdR32LVuU7WNkiu55XI5/ZXRgV6PNN3tOEHPLxn1Wl5cZ4kbQbciAF+eo0JAgMBAAECggEAC/BtdoTWWDUFXL0Pq1gaNkxzltehmV8B+U2FFZ4L8vX648t5Qn2SxAcxBEfMCxnkk/uJ1yfobAC1raZHaNbTMacmUz1mJzZwLm7GzG0JODh3ZcS0PQAA4Wj/aPKr994v08jeA0DJ2zAmx0xR2vF24oE9uxja9pN8dCleJD4kvCR1aVMJBlUow09PnZo6fsi9wAdIjs/BHVQT0mUl7Nx+fFqhLbWgJB3+EdB2sudiQ6r4P622zNR0BAeYuoS93LTFTER/6QYRYfQ4+aVYCacJs9hI0L+2SQmEteF+TS4P2PQxvryvmcYYGRnfQLtmQmdLU54eHkaY88+gKGoN9cxbbwKBgQDP/4qExV7lNhgpHnlv9KwXSRLk3nHvShqWKBm1ofRxGvF8bhp2s/6AG88AiGOUzMMJiS6sFasx6upznzWRUU6wpQYPP8SIftYPCv2f0dm4lIxi+o9KJHbt2zXYkoEwhgaWwo2h/InzWksVV4nRh1nm9UfUWbhGPg0f/DCjcjFgAwKBgQDihBjlN5HVhXn/PTmYRdad5Gv7wsRuJS3eSn0qSW2wHyQTav/4ulx5R21Vjbos5hEfP9wSzypy8VUgtpr9hWaWrV4noPInuo/STsUVYmdC81B3/dNWCVJQOVWogK6uD8Rh7jYPcR9fGMAiliYAygGekVNmy66r9talVLjkPmzPAwKBgQDAMWNATdPivjpS/Gq/rXi6x3Xi7zyeHH42k3U2JSFmxbuv+1kOqEEZBRkgZ+aEHzR1AkKTFi6rIGNlVQ69aUDp7oKL4qNqcLDBE6nJXLHuYaza5KU0oD8Yh/7YUH95Y86AzeLrdBvQNnW8kbeyWXwT8j9eE0038qxUCsaysJi5GwKBgQC8VYzFeHCekb4fg+5RNy/8U6Gc0BG2at86RcDP2gGDQEEkjACL85dTlxnG2nIDRr7RtqzqTqlCrHlVG76+L55ehYMVe/IbKjjOaYPgBdNJjThIrBh9Hn78CM+5rFSQkLd9nSwBptKopNGLcD/kxBCYoMgxXgS7Ih7RlCGuVGDvtQKBgQDFXhexzngPKboXvKl9rz19DSZ98IIbNTwX7Svc5rfvKGHN0XMGpc93SXA4WBY8ZlX6M/NNRk2Gd9ePf64dhn2uViMMAGwvsadiCV6Z2BqpQnDGKq2VpAbuFqtnCDPIfgPKY4fbHFPjcO3n/+wFqTL6grbIP7yM76Fv0oqt+/t2Yw==

key id: 1151022712

python code output:

Message to sign: 11510227122024-12-19T08:48:29.528457+00:00
b'11510227122024-12-19T08:48:29.528457+00:00'
{
  "keyId": "1151022712",
  "timestamp": "2024-12-19T08:48:29.528457+00:00",
  "signature": "gumnKBrIiRn4nlxOYe+2JASgngiFh71jpX8u/wfqH0bOw2S3B+X3sk+2pCYc9w3bmjZL2uMwAcb8dnN8UEZFKs03xo4s4RFjaqQpfwCKv1IFidNhilIiF7oyx2PkGBxVVAMtH0srO6wxmYKGFjOvCNSS5/edM7AwuXb4ZRe+6wQrmNMV/nwiKQ3Onqc5SnyaFjxINLo2/eiG4Ks0ngkmdT6PhPYhTW8Zy0EAZszo0ZK3W6z+uEMfQxw1veFa0TqcdJSQws9YZZIqBdw8mbZmY1CUZD7SwPT3UQZRw6eJezBtq/wcNO/afaW2MB9ejpkxNYr/+cFYglBTbNaZLzOK9g=="
}

elixir code output:

{:ok,
 %{
   timestamp: "2024-12-19T08:48:29.528457+00:00",
   signature: "lXl157EEip2OVA0UpR72oAiEjER0eDRXr5kr4fujwSZLj0/KPfkO5+1tRKY2rJVGIQ6/FAlMDtQqTijltLBvZXGqf8YWhU0zYiAzHmPZZ5WDg4Z08vwjhMDnhtsxk7MtTbv1ZzLPolCg0LOMlZqmVDaCADMl8QB9c8CHXKOogBGUP50+ML25OCvV6Ti9ni8QFfLR91fBeBYTFf0dZNqxOM/T3wX6qUAAcDnl0624Cp/UJOwDiHOivSYZJ+qsvR4ExoSYAK2RbZZOHuOIA2GrPgAOxsDjvHlBkMAa+e2lPdlAC6h7Thqla7sojeySiPWbkVf4KADBNOGisEVrnI0FaA==",
   keyId: "1151022712"
 }}

I tried different libs for working with rsa in elixir, but my elixir code output always mismatch with python code output. I am new to cryptography, maybe I am making some mistake? How to make signatures match?

0

1 Answer 1

2

Both codes generate different signatures, as the Elixir code does something different to the Python code:
In the Elixir code, first the SHA-512 hash of the message is generated and the result is hex encoded (with lowercase letters). This result is then hashed with SHA-1 and signed.
In the Python code, on the other hand, the message is "only" hashed and signed with SHA-512.

So that the Elixir code does the same as the Python code, you should omit the first hashing with SHA-512. When signing, you should use the message directly and SHA-512 as digest:

defmodule RsaExample do
  require Logger

  defp api_key() do
    #Application.get_env(:rsa_example, :api_key)
    "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4CuxG1G1KiXFWpLXAGWI0ATKRP+Ixto9ElVqpFsPRB14Cu0TaRA6rEMW2C8LgafUYAJdrfzypB1tlfPpRH1fpQoFNkbYnec5/DJGMrh4fWkSZEflrOcSnY0CEHVG2fO0AMT4toVmgj6svfBSMf6S2sm2rjhQjMSqj87wOG3TNaIvQSaAz7UXa+hzaI7LQ0a41iUUDI6JLYH1EbvjZQQhwjgWlqy5LSeosBXtpPyfLaQDfUaV8eAB5mCt6uV5NlCGKMpvT+h9ZvT8gRn9P9PQeCScFyNdR32LVuU7WNkiu55XI5/ZXRgV6PNN3tOEHPLxn1Wl5cZ4kbQbciAF+eo0JAgMBAAECggEAC/BtdoTWWDUFXL0Pq1gaNkxzltehmV8B+U2FFZ4L8vX648t5Qn2SxAcxBEfMCxnkk/uJ1yfobAC1raZHaNbTMacmUz1mJzZwLm7GzG0JODh3ZcS0PQAA4Wj/aPKr994v08jeA0DJ2zAmx0xR2vF24oE9uxja9pN8dCleJD4kvCR1aVMJBlUow09PnZo6fsi9wAdIjs/BHVQT0mUl7Nx+fFqhLbWgJB3+EdB2sudiQ6r4P622zNR0BAeYuoS93LTFTER/6QYRYfQ4+aVYCacJs9hI0L+2SQmEteF+TS4P2PQxvryvmcYYGRnfQLtmQmdLU54eHkaY88+gKGoN9cxbbwKBgQDP/4qExV7lNhgpHnlv9KwXSRLk3nHvShqWKBm1ofRxGvF8bhp2s/6AG88AiGOUzMMJiS6sFasx6upznzWRUU6wpQYPP8SIftYPCv2f0dm4lIxi+o9KJHbt2zXYkoEwhgaWwo2h/InzWksVV4nRh1nm9UfUWbhGPg0f/DCjcjFgAwKBgQDihBjlN5HVhXn/PTmYRdad5Gv7wsRuJS3eSn0qSW2wHyQTav/4ulx5R21Vjbos5hEfP9wSzypy8VUgtpr9hWaWrV4noPInuo/STsUVYmdC81B3/dNWCVJQOVWogK6uD8Rh7jYPcR9fGMAiliYAygGekVNmy66r9talVLjkPmzPAwKBgQDAMWNATdPivjpS/Gq/rXi6x3Xi7zyeHH42k3U2JSFmxbuv+1kOqEEZBRkgZ+aEHzR1AkKTFi6rIGNlVQ69aUDp7oKL4qNqcLDBE6nJXLHuYaza5KU0oD8Yh/7YUH95Y86AzeLrdBvQNnW8kbeyWXwT8j9eE0038qxUCsaysJi5GwKBgQC8VYzFeHCekb4fg+5RNy/8U6Gc0BG2at86RcDP2gGDQEEkjACL85dTlxnG2nIDRr7RtqzqTqlCrHlVG76+L55ehYMVe/IbKjjOaYPgBdNJjThIrBh9Hn78CM+5rFSQkLd9nSwBptKopNGLcD/kxBCYoMgxXgS7Ih7RlCGuVGDvtQKBgQDFXhexzngPKboXvKl9rz19DSZ98IIbNTwX7Svc5rfvKGHN0XMGpc93SXA4WBY8ZlX6M/NNRk2Gd9ePf64dhn2uViMMAGwvsadiCV6Z2BqpQnDGKq2VpAbuFqtnCDPIfgPKY4fbHFPjcO3n/+wFqTL6grbIP7yM76Fv0oqt+/t2Yw=="
  end

  defp key_id() do
    #Application.get_env(:rsa_example, :key_id)
    "1151022712"
  end

  def get_signature do
    dt = "2024-12-19T08:48:29.528457+00:00"

    #message =
    #  :crypto.hash(:sha512, key_id() <> dt)
    #  |> Base.encode16()
    #  |> String.downcase()
    message = key_id() <> dt # fix1: apply the message directly

    api_key = Base.decode64!(api_key())
    <<_::binary-size(26), der::binary>> = api_key

    key = :public_key.der_decode(:RSAPrivateKey, der)
    signature = :public_key.sign(message, :sha512, key) |> Base.encode64() # fix2: apply SHA-512

    {:ok,
      %{
        keyId: key_id(),
        timestamp: dt,
        signature: signature
      }}
  end
end

IO.inspect RsaExample.get_signature() #... signature: "gumn...OK9g==",...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.