Modular Exponentiation is an operation that is used quite frequently
in areas such as cryptography. The Diffie-Hellman method is a prime
(pun intended) example.
I actually use the below function with the parameters shown for some
unique purposes... but it has limited use in most real world
programming; due to the fact that it can only handle the relatively
small values shown. Remember, something like the Diffie-Hellman
method is normally using 300 digit or larger numbers... that means
that DH calls for a bignum library.
So just consider this an educational example of how binary
exponentiation works.
Note:
If anybody wants to help me out by explaining why the intermediate
result inside the function is only updated when working with the ones
bits of the exponent - feel free! I wrote this a few years ago, and
every time I use it I wonder about that.
I've seen lots of examples on the web, but I've never seen code that
even comes close to commenting correctly about why the individual
steps are doing what they do... which is ridiculous considering that
there are so few steps involved and that it is a function that is in
great use. Hopefully, this will help someone else.
Code: Select all
CONST DBGPRINT = false
' -------------------------------
' Modular Exponentiation
' -------------------------------
Function Modular_Exponentiation(base_num as ulong, exponent as ulongint, modulus as ulong) as ulong
' Modular Exponentiation by Repeated Squaring - (Binary Exponentiation)
'
' Modular Exponentiation - Wikipedia
' https://en.wikipedia.org/wiki/Modular_exponentiation
'
' We are able to directly calculate things, like a 32-bit number
' raised to the power of a 64-bit number and then take the
' modulo of that result by a 32-bit number, by utilizing a
' numerical method called "repeated squaring" to break the
' exponentiation down into a series of smaller exponentiations
' that are manageable without the need for a BIGNUM library.
'
dim b1 as ulongint = base_num
dim e1 as ulongint = exponent
dim result as ulongint = 1
' ' This temp var is just so I can print which
' ' bit of the exponent I'm working on below.
' dim i_bit as Integer = 0
' IF DBGPRINT THEN
' print "INIT base = "; b1
' print "INIT exponent (priv) = "; e1
' print "INIT modulus = "; modulus
' print "INIT result = "; result
' END IF
'
b1 = b1 MOD modulus
' IF DBGPRINT THEN
' print "b1 MOD modulus = "; b1
' print
' END IF
'
' Binary Exponentiation...
' ... We're working with the exponent as a series of bits.
' We will be doing a SHR on the exponent in every pass of the
' loop in order to get at the exponent's next bit.
' When all of the ones bits are gone (leaving exponent = 0),
' then we are done with the exponentiation.
do while exponent > 0
' IF DBGPRINT THEN
' print "DO exponent = "; bin(exponent,32)
' END IF
' Binary Exponentiation...
' ... We're working with the exponent as a series of bits.
' If bit zero of the remaining exponent bits is a one bit...
if (exponent and 1) then
' I'm not a maths guy... I don't know why we are only
' updating the result when working with the ones bits
' of the exponent.
' The equation just says to do this now.
result = (result * b1) MOD modulus
' IF DBGPRINT THEN
' print "result*b1 MOD modulus = "; result
' END IF
end if
' IF DBGPRINT THEN
' print "b1 = "; b1
' END IF
'
' IF DBGPRINT THEN
' ' We want to see both the square and the MOD results.
' print "(b1 ^ 2) = "; (b1 * b1)
' END IF
b1 = (b1 * b1) MOD modulus
' IF DBGPRINT THEN
' ' We want to see both the square and the MOD results.
' print "b1 MOD modulus = "; b1
' END IF
'
' Binary Exponentiation...
' ... We're working with the exponent as a series of bits.
' Shift the exponent right one bit to get at the next bit.
exponent = exponent shr 1
' IF DBGPRINT THEN
' ' Track which bit of the exponent is next...
' i_bit += 1
' print i_bit; tab(3); " - exponent SHR = "; bin(exponent,32)
' print
' END IF
loop
' IF DBGPRINT THEN
' print "RESULT ................ "; result; " "; ucase(hex(result))
' print
' print
' END IF
'
return result
end function
' ------------------------------------------------------------
dim base_num as ulong = 5
dim exponent as ulongint = 2982377858398747
' This is the largest 32-bit prime. It will result in the largest
' 32-bit result set.
dim modulus as ulong = 4294967291
'
dim result as ulong = 0
'
result = Modular_Exponentiation(base_num, exponent, modulus)
print "result = "; result
end