Птицу узнают по перьям… или профзащита от спама

от автора

Часто у каждого из нас возникает желание найти похожих на себя (в профессиональном смысле), но в то же время размещение в публичных сетях своей контактной информации может породить кучу спама (ах эти древние консервы).
На помощь в этом случае приходит общее знание — образовательный ценз в профессиональной области — которое не даст воспользоваться данными «непосвящённым».

Примите и эту простую защиту персональных данных для математиков и программистов.

Вспомним одну из первых систем ассиметричного шифрования RSA — что лежит в её основе?
Простой факт:
если для числа m известно значение функции Эйлера E(m),
то для любого a != 0 выполняется a ^ E(m) % m = 1

А значит, если p и E(m) взаимно просты, то есть существуют c и d, такие что c*p + d*E(m) = 1, и s = c % E(m)
то для любого a из [0,m) выполняется a ^ (s*p) % m = a

Воспользуемся этим.
Набросаем программку на js (надеюсь читающие это в браузере знают как заходить в консоль)

function split(x) {     for (let i = 2n; i * i <= x; i++) {         let j = x / i;         if (i * j == x) return [i, j];     } }  function toPrimes(x) {     let arr = [x];     let primes = [];     while (arr.length > 0) {         let x = arr.pop();         let s = split(x);         if (s) s.forEach(y => arr.push(y));         else primes.push(x);     }     primes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);     return primes; }  function euler(p) {     let z = 1n;     let map = new Map();      p.forEach(x => {         let value = 0n;         if (map.has(x)) { value = map.get(x); map.delete(x); }         value++;         map.set(x, value);     });     for (let [key, value] of map.entries()) {         z *= pow(key, value) - 1n;     }     return z; }  function xgcd(a, b) {     if (!b) return [1n, 0n];     let [c, d] = xgcd(b, a % b);     let q = a / b;     return [d, c - d * q]; }  function pow(x, y) {     if (!y) return 1n;     let h = y / 2n;     let z = pow(x, h);     let r = (z * z);     if (y % 2n) r = (r * x);     return r; }  function powmod(x, y, m) {     if (!y) return 1n;     let h = y / 2n;     let z = powmod(x, h, m);     let r = (z * z) % m;     if (y % 2n) r = (r * x) % m;     return r; }  let p = 3n; let q = 11n; let m = pow(10n, q) + 1n;  let primes = toPrimes(m); let z = euler(primes); let primes2 = toPrimes(z); while (primes2.find(x => (p / x) * x == p)) p += 2n; let [c, d] = xgcd(p, z);  let s = c >= 0n ? c : (z + c);  function get(x) {     let t = powmod(x, s, m);     console.log(`(${t} ** ${p}) % (10 ** ${q} + 1) =`, powmod(t, p, m)); }  console.assert(powmod(275491122648n, 7n, pow(10n, 13n) + 1n) == 81234567890n);  get(81234567890n); 

Запускаем, проверяем, получаем

(83735460521 ** 13) % (10 ** 11 + 1) = 81234567890n

Работает машинка английская?

UPD.
Ха-ха — судя по рейтингу статьи (-4 на 17.03.2024) — работает машинка английская…


ссылка на оригинал статьи https://habr.com/ru/articles/800345/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *