Zulip Chat Archive
Stream: mathlib4
Topic: Cannot use `Nat.ModEq.pow_totient` (Euler's theorem)
ElCondor (Nov 11 2023 at 12:37):
I'm trying to use Euler's theorem, as implemented in https://github.com/leanprover-community/mathlib4/blob/7766bcc46ae69e55b32297edb59448f2e1fe1dde/Mathlib/FieldTheory/Finite/Basic.lean#L474
However, even using it in the most basic form doesn't seem to work: see here.
It looks like rw
is looking for an expression like x ^ φ n % n
and won't accept something like x ^ φ n ≡ 1 [MOD n]
.
What am I doing wrong?
Kevin Buzzard (Nov 11 2023 at 15:38):
The rw
tactic will only eat theorems of the form A = B
or A ↔ B
. And when it eats one of these, it will change all A
s to B
s. You don't have this set-up, because you have a congruence, not an equality. You could turn it into an equality in , but Lean is picky about these things.
example {x n : ℕ} (h0 : Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by
apply Nat.ModEq.pow_totient h0
ElCondor (Nov 13 2023 at 14:45):
Kevin Buzzard said:
The
rw
tactic will only eat theorems of the formA = B
orA ↔ B
. And when it eats one of these, it will change allA
s toB
s. You don't have this set-up, because you have a congruence, not an equality. You could turn it into an equality in , but Lean is picky about these things.example {x n : ℕ} (h0 : Coprime x n) : x ^ φ n ≡ 1 [MOD n] := by apply Nat.ModEq.pow_totient h0
OK I understand.
I switched to using ZMod
instead, and I was able to prove a part of what I want (proving a result related to RSA) using these: see live.
Now using eq0 : (M ^ e) ^ d = M
(in terms of (ZMod (p * q))ˣ
objects) I'd like to switch back to m = ((m ^ e) ^ d) % (p * q)
(in terms of integers).
I guess that involves coercions at some point but honestly I have no idea how to proceed. Would someone be able to help me? (regarding the first case of by_cases
only, I'll try to implement the other one on my own)
Kevin Buzzard (Nov 13 2023 at 15:20):
{
let M : Units (ZMod (p * q)) := ZMod.unitOfCoprime _ h
have eq0 : (M ^ e) ^ d = M := by calc
(M ^ e) ^ d = M ^ (e * d) := by rw [<-pow_mul]
_ = M ^ (1 + φ (p * q) * k) := by rw [hde]
_ = M * (M ^ φ (p * q)) ^ k := by rw [pow_add, pow_one, pow_mul]
_ = M := by rw [ZMod.pow_totient M]; simp
-- eq0 is an equality in (Z/pqZ)^*. Change it to an equality in Z/pqZ
replace eq0 := congrArg Units.val eq0
-- now move the "invisible to mathematicians" map from (Z/pqZ)^* to Z/pqZ so that
-- it applies directly to M, not (M^e)^d
push_cast at eq0
-- Now turn M back into m
simp only [unitOfCoprime] at eq0
-- now move the "invisible to mathematicians" map from Z to Z/pqZ so it applies
-- to (m^e)^d not m
norm_cast at eq0
-- now use the lemma saying (↑a : ZMod n) = (↑b : ZMod n) ↔ a % n = b % n
rw [nat_cast_eq_nat_cast_iff'] at eq0
-- and now we can rewrite it in the goal
rw [eq0]
-- and finally apply the lemma saying a % b = a if a < b
exact (mod_eq_of_lt hm).symm
}
This really is harder than it should be, but there's my effort.
Last updated: Dec 20 2023 at 11:08 UTC