Skip to content

Commit

Permalink
descriptiveness
Browse files Browse the repository at this point in the history
  • Loading branch information
zardus committed Sep 30, 2024
1 parent 64a7bdf commit 66212f7
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
6 changes: 3 additions & 3 deletions cryptography/level-6/DESCRIPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ Let's take it step by step:
1. First, Alice and Bob agree on a large prime number `p` to define their Finite Field (e.g., all further operations occur _modulo `p`_: a context where numbers go from `0` to `p-1`, and then loop around), along with a _root_ `g`, and exchange them in the open, content to let Eve see them.
2. Then, Alice and Bob each generate a _secret_ number (`a` for Alice's and `b` for Bob's).
These numbers are never shared.
3. Alice computes `A = (g ** a) % p` (`g` to the `a` power modulo `p`) and Bob computes `B = (g ** b) % p`.
3. Alice computes `A = (g ** a) mod p` (`g` to the `a` power modulo `p`) and Bob computes `B = (g ** b) mod p`.
Alice and Bob exchange `A` and `B` in the open.
4. At this point, Eve will have `p`, `g`, `A`, and `B`, but will be unable to recover `a` or `b`.
If it wasn't for the finite field, recovering `a` and `b` would be trivial via a logarithm-base-`g`: `log_g(A) == a` and `log_g(B) == b`.
However, this does not work in a Finite Field under a modulo because, conceptually, we have no efficient way to determine how many times the `g ** a` computation "looped around" from `p-1` to `0`, and this is needed to compute the logarithm.
This logarithm-in-a-finite-field problem is called the [Discrete Logarithm](https://en.wikipedia.org/wiki/Discrete_logarithm), and there is no efficient way to solve this without using a quantum computer.
Quantum computers' ability to solve this problem is the most immediate thing that makes them so dangerous to cryptography.
5. Alice calculates `s = (B ** a) % p`, and since `B` was `(g ** b) % p`, this results in `s = ((g ** b) ** a) % p` or, applying middle school math, `s = (g ** (b*a)) % p`.
Bob calculates `s = (A ** b) % p`, and since `A` was `(g ** a) % p`, this results in `s = (g ** (a*b)) % p`. Since `a*b == b*a`, the `s` values computed by both Bob and Alice are equal!
5. Alice calculates `s = (B ** a) mod p`, and since `B` was `(g ** b) mod p`, this results in `s = ((g ** b) ** a) mod p` or, applying middle school math, `s = (g ** (b*a)) mod p`.
Bob calculates `s = (A ** b) mod p`, and since `A` was `(g ** a) mod p`, this results in `s = (g ** (a*b)) mod p`. Since `a*b == b*a`, the `s` values computed by both Bob and Alice are equal!
6. Eve _cannot_ compute `s` because Eve lacks `a` or `b`.
Eve could compute `A ** B == g ** a ** g ** b`, which reduces to something like `g ** (a*(g**b))` and doesn't get Eve any closer to `s`!
Eve could also compute `A * B == (g ** a) * (g ** b) == g ** (a+b)`, but again, this is not the `s == g ** (a*b)` that Bob and Alice arrived at.
Expand Down
29 changes: 28 additions & 1 deletion cryptography/level-7/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,29 @@
Diffie-Hellman allow Alice and Bob to generate a single (but uncontrolled) shared secret with no pre-shared secret information.
Next, we'll learn about another cryptosystem, [RSA (Rivest–Shamir–Adleman)](https://en.wikipedia.org/wiki/RSA_(cryptosystem)), that allows Alice and Bob to generate arbitrary amounts of controlled messages, with no pre-shared secret information!

RSA uses a clever interaction of modular exponentiation (which you've experienced in DH) and [Euler's Theorem](https://en.wikipedia.org/wiki/Euler%27s_theorem) to give Bob or Alice _asymmetric_ control over an entire finite field.
Alice generates two primes, `p` and `q`, _and keeps them secret_, then multiplies them to create `n = p*q`, which Alice publishes to define a Finite Field modulo `n`.
Euler's Theorem and knowledge of `p` and `q` gives Alice, _and only Alice_, full abilities within this specific field (which is a difference from DH, where all actors have equal capabilities in the field!).

Euler's Theorem tells us that operations _in an exponent_ of a field modulo `p*q` (e.g., the `e*d` of `m**(e*d) mod n`) take place in the field of `(p-1)*(q-1)`.
The _why_ of this theorem is some advanced math stuff that, to be honest, few people understand, but the results are interesting.
Computing `(p-1)*(q-1)` is trivial for Alice (armed with knowledge of `p` and `q`) but impossible to anyone else (assuming that `p` and `q` are large), because the human race lacks an efficient algorithm to factor products of large prime numbers!

Recall that `e*d` in the exponent of `m**(e*d) mod n`?
For any `e`, knowing `(p-q)*(q-1)` allows Alice to compute a `d` such that `e*d == 1`.
While this seems silly, it is the core of RSA.
Alice chooses a number `e` (typically fairly small to reduce computation costs, but not too small to cause certain security issues) and computes the corresponding multiplicative inverse `d`.
This leads to encryption of plaintext `m` (`m**e mod n == c`) and decryption! `c**d mod n == (m**e)**d mod n == m**(e*d) mod n == m**1 mod n == m`.
Rather than DH's single and uncontrolled `s`, RSA messages `m` can be chosen arbitrarily (up to the size of `n`, as the field is unable to represent larger numbers).

RSA is _asymmetric_.
Alice shares `n` and `e` as the public key, and keeps `d` as the private key.
Knowing `n` and `e`, Bob can encrypt messages and send them to Alice, and only Alice can decrypt them.
Since `e*d == d*e`, Alice _can_ use `d` to encrypt messages, but _anyone_ can decrypt them, since `e` is public.
This might sound silly, but it is useful for, e.g., attesting that a given message could come only from Alice, since knowledge of `d` is required for this.

To respond to Bob, Alice would need Bob's own public key, which would be _Bob's_ `n` (different from Alice's `n`, using Bob's own secret `p` and `q`!) and `e` (which is typically the same smallest-safe value, currently `65537` but subject to change as new attacks are found).

In this challenge you will decrypt a secret encrypted with RSA (Rivest–Shamir–Adleman).
You will be provided with both the public key and private key.
You will be provided with both the public key and private key this time, to get a feel for how all this works.
Go for it!
6 changes: 3 additions & 3 deletions cryptography/level-7/run
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ flag = open("/flag", "rb").read()
assert len(flag) <= 256

key = RSA.generate(2048)
print(f"e = {key.e:#x}")
print(f"d = {key.d:#x}")
print(f"n = {key.n:#x}")
print(f"(public) n = {key.n:#x}")
print(f"(public) e = {key.e:#x}")
print(f"(private) d = {key.d:#x}")

ciphertext = pow(int.from_bytes(flag, "little"), key.e, key.n).to_bytes(256, "little")
print(f"Flag Ciphertext (b64): {b64encode(ciphertext).decode()}")

0 comments on commit 66212f7

Please sign in to comment.