Also shown is some code to encrypt a message (very short one character "A" represented by ASCII 65) and decrypt it back to the original. To encrypt a larger message needs an arithmetic vehicle larger that that available in VBA, you'll see I'm declaring variables as Currency to get as many bits as possible but even this has limits when raising a number to a very high power exponentional.
Anyway, simple version that allows VBA programmer to step through the wikipedia example is given here ...
Option Explicit
Option Private Module
Private Type udtPublicKey
n As Currency
e As Currency
End Type
Private Type udtPrivateKey
n As Currency
d As Currency
End Type
'***************************************************
' .__
' _____ _____ |__| ____
' / \\__ \ | |/ \
'| Y Y \/ __ \| | | \
'|__|_| (____ /__|___| /
' \/ \/ \/
'***************************************************
Private Sub Main()
Dim p As Currency
Dim q As Currency
Dim n As Currency
Dim lambda_n As Currency
Dim e As Currency
Dim d As Currency
p = 61
q = 53
n = p * q
lambda_n = Application.Lcm(p - 1, q - 1)
e = 17
Debug.Assert IsCoPrime(e, lambda_n)
d = ModularMultiplicativeInverse(e, lambda_n)
Debug.Assert e <> d
Dim uPrivate As udtPrivateKey
uPrivate.d = d
uPrivate.n = n
Dim uPublic As udtPublicKey
uPublic.e = e
uPublic.n = n
'* m is the message to encrypt, it needs to be a number
'* 65 is ASCII for "A"
Dim m As Currency
m = 65
'* c is the encrypted message
Dim c As Currency
c = Encrypt(m, uPublic)
'* m2 is the decrypted message
Dim m2 As Currency
m2 = Decrypt(c, uPrivate)
'* and the decrypted message should match the original
Debug.Assert m2 = m
End Sub
Private Function Encrypt(ByVal m As Currency, _
ByRef uPublic As udtPublicKey) As Currency
If m > uPublic.n Then Err.Raise vbObjectError, , _
"#text is bigger than modulus, no way to decipher!"
Dim lLoop As Long
Dim lResult As Currency
lResult = 1
For lLoop = 1 To uPublic.e
lResult = ((lResult Mod uPublic.n) * (m Mod uPublic.n)) Mod uPublic.n
Next lLoop
Encrypt = lResult
End Function
Private Function Decrypt(ByVal c As Currency, _
ByRef uPrivate As udtPrivateKey) As Currency
If c > uPrivate.n Then Err.Raise vbObjectError, , _
"#text is bigger than modulus, no way to decipher!"
Dim lLoop As Long
Dim lResult As Currency
lResult = 1
For lLoop = 1 To uPrivate.d
lResult = ((lResult Mod uPrivate.n) * (c Mod uPrivate.n)) Mod uPrivate.n
Next lLoop
Decrypt = lResult
End Function
Private Function IsCoPrime(ByVal a As Currency, ByVal b As Currency) As Boolean
IsCoPrime = (Application.Gcd(a, b) = 1)
End Function
Private Function ModularMultiplicativeInverse(ByVal e As Currency, _
ByVal lambda_n As Currency)
Dim lLoop As Currency
For lLoop = 1 To lambda_n
If lLoop <> e Then
Dim lComp As Currency
lComp = lLoop * e Mod lambda_n
If lComp = 1 Then
ModularMultiplicativeInverse = lLoop
Exit Function
End If
End If
Next
SingleExit:
End Function
No comments:
Post a Comment