Skip to content

Instantly share code, notes, and snippets.

@atierian
Created March 23, 2021 13:17
Show Gist options
  • Select an option

  • Save atierian/dd12aca9e0c289688518d9175eb34e3a to your computer and use it in GitHub Desktop.

Select an option

Save atierian/dd12aca9e0c289688518d9175eb34e3a to your computer and use it in GitHub Desktop.
Basic example showing how RSA encryption works
/// Select two prime numbers `p` and `q` (generally very large numbers, but using small numbers due to limitations of UInt)
let p: UInt = 5
let q: UInt = 7
/// `n` is the product of `p` and `q`
let n: UInt = p * q //35
/// `r` is `(p - 1) * (q - 1)`
let r: UInt = (p-1) * (q-1) //24
/// Determine potential `k` candidates, where each potential `k` is `r * x + 1`
let candidates = (1...30).map { r * $0 + 1 }
/// Find a `k` that factors to `e` and `d` where both `e` and `d` are relatively prime to `n` and `e * d == 1 % r`
func generateKeys(from k: UInt) -> Keys? {
for eCandidate in 3...k/3 where k % eCandidate == 0 {
let dCandidate = k / eCandidate
guard areCoprime(eCandidate, r),
areCoprime(dCandidate, r)
else { continue }
return Keys(e: eCandidate, d: dCandidate)
}
return nil
}
func areCoprime(_ m: UInt, _ n: UInt) -> Bool {
var a: UInt = 0
var b: UInt = max(m, n)
var r: UInt = min(m, n)
while r != 0 {
a = b
b = r
r = a % b
}
return b == 1
}
/// Key contains properties `e` and `d`, where `e` is the public key and `d` is the private key
let keys = candidates.compactMap { generateKeys(from: $0) }.first //e = 5, d = 5
/// Message to encrypt
let message: [UInt] = [7, 4, 5, 12, 22, 25, 33, 1, 14, 34]
/// Enrypt message with `message^e % n`
func encrypt(message: [UInt], e: UInt, n: UInt) -> [UInt8] {
message.map {
UInt8(
UInt( pow(Double($0), Double(e) )
) % n
)
}
}
/// Encrypted message
let encrypted = encrypt(message: message, e: keys!.e, n: n) // [7, 9, 10, 17, 22, 30, 3, 1, 14, 34]
/// Decrypt encrypted message with `encrypted^d % n`
func decrypt(_ encrypted: [UInt8], d: UInt, n: UInt) -> [UInt8] {
encrypted.map {
UInt8(
UInt( pow(Double($0), Double(d) )
) % n
)
}
}
/// Decrypted message
let decrypted = decrypt(encrypted, d: keys!.d, n: n) // [7, 4, 5, 12, 22, 25, 33, 1, 14, 34]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment