Claudio Cherubino's blog Life of a Googler

1Dec/082

Implementation of RSA in F#

During my university course I had to learn and use two functional programming languages: Haskell and Scheme. I fell in love with the former but I never managed to do the same with the syntax of Scheme and the incredibly huge number of parenthesis you have to type in order for your code to work!

That's why I decided to steal borrow a short implementation of the RSA algorithm written in Scheme and translate it into F#.

As you may know, RSA is an algorithm used for public-key encryption based on prime numbers and factorization that is widely use on the web to secure e-commerce transactions.

At the end of the following code there is also a working example that can be executed to better understand the steps required to encrypt and decrypt a message (in this case a single number):

#light
// Modulus operator that handles negative numbers correctly
let modulus n m =
  ((n % m) + m) % m

// Greater Common Divisor
let rec gcd a b =
  match b with
  | b when b = 0 -> a
  | b -> gcd b (a % b)

// extended_gcd = (x,y), such that a*x + b*y = gcd(a,b)
let rec extended_gcd a b =
  if (a % b = 0) then
    (0, 1)
  else
    let (x, y) = extended_gcd b (a % b)
    (y, x - y * (a / b))

// modulo_inverse(a,n) = b, such that a*b = 1 [mod n]
let modulo_inverse a n =
  let (x, y) = extended_gcd a n
  modulus x n

// totient(n) = (p - 1)*(q - 1),
// where pq is the prime factorization of n.
let totient p q = (p - 1) * (q - 1)

// square(x) = x^2
let square x = x * x

// modulo-power(base,exp,n) = base^exp [mod n]
let rec modulo_power b exp n =
  if (exp = 0) then
    1
  else
    if (exp % 2 = 1) then
      (((modulo_power b (exp - 1) n) * b) % n)
    else
      ((square (modulo_power b (exp / 2) n)) % n)

// RSA routines.

// A legal public exponent e is between
// 1 and totient(n), and gcd(e,totient(n)) = 1
let is_legal_public_exponent e p q =
  (1 < e) && (e < (totient p q)) && (1 = (gcd e (totient p q)))

// The private exponent is the inverse of the public exponent, mod n.
let private_exponent e p q =
  if (is_legal_public_exponent e p q) then
    modulo_inverse e (totient p q)
  else
    raise (new System.Exception("Not a legal public exponent for that modulus"))

// An encrypted message is c = m^e [mod n]
let encrypt m e n =
  if (m > n) then
    raise (new System.Exception("The modulus is too small to encrypt the message"))
  else
    modulo_power m e n

// A decrypted message is m = c^d [mod n]
let decrypt c d n =
  modulo_power c d n

// RSA example.
let p = 61
let q = 53
let n = p * q
let e = 17
let d = private_exponent e p q
let message = 123
let c = encrypt message e n
let m = decrypt c d n

I think the code presented is self-explainatory and each function is briefly described in the comments, but there is a strange thing that you may have noticed.

The first function I defined is the modulus operator, but F# already has a modulus operator, so why bothering?

Before writing that function I was about to getting crazy, since everything else was already written but the encryption was not working properly. I debugged and tested again and again and eventually I found out that sometimes the result of the native modulo operation was a negative number.

After a short lookup on Wikipedia, I discovered that each programming language implements the modulo operator differently and while in Scheme the result has the same sign as the divisor, in F# the sign of the result is the same as the dividend!

8Feb/084

Project Euler in F# – Problem 5 (alternative solution)

There was some buzz concerning my last post on Project Euler Problem 5, since the solution presented implemented a naive brute-force algorithm and its performance was very poor.

In my mind it was only meant to be an introductory article devoted to presenting a first solution to a common problem, the least common multiple (LCM) of a set of numbers, and I planned to write a second post (the one you are reading now) to show how a "smart" algorithm could lead to outstanding performance.

Let's read the text of the exercise another time:

2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?

As we already explained, the exercise just asks us to find the least common multiple of all numbers from 1 to 20, and we can compute it by using the greatest common divisor of these numbers.

In fact, we have that:

lcm (a,b) = a * b / gcd (a,b)

In order to compute the LCM of the numbers from 1 to 20, we start computing the LCM of the first two numbers (1 and 2) and then we go on computing the LCM of the result and the third element of the sequence. We go on this way until all elements have been included in the computation.

The application of the same function to all elements of a sequence while keeping an "accumulator" is called folding, and it is a common practice in functional programming.

Let's look at the code:

#light
open Microsoft.FSharp.Math.BigInt

// Greater Common Divisor
let rec gcd a b =
 match b with
 | b when b = 0I -> a
 | b -> gcd b (a % b)

// Least Common Multiple
let lcm a b = a * b / (gcd a b)

let answer = Seq.fold1 lcm [1I .. 20I]

At line 11 we defined the least common multiple as explained above, while at line 5 we have the implementation of the Euclidean algorithm for the Greatest Common Divisor.

Then we simply fold the lcm function on the sequence [1 .. 20] and we get the output.

Do you remember how much time our "optimized" algorithm in the last article takes to perform the same calculation? 25 seconds.

The solution presented here only needs 15 milliseconds!