Нашёл код очень интересной системы. Привожу ниже.
Yozhix-6969
Сообщений 1 страница 3 из 3
Поделиться22018-10-19 23:27:48
<html> <head> <title>Yozhix-6969</title> <meta charset="utf-8"> </head> <body style="background-color:#fa0"> <table style="width:100%;height:100%"> <tr> <td colspan="2"> <table style="width:100%"> <tr> <td><input type="button" value="Зашифровать" title="Зашифровать исходный текст" onClick="perePro1()"></td> <td style="width:25%;text-align:center">Исходный текст</td> <td style="width:50%;text-align:center"> <nobr>Ключ <input id="key" type="password" size="13" title="Ключ шифрования (пароль, секретное слово)"></nobr> <nobr>повтор <input id="key2" type="password" size="13" title="Повтор ключа для избежания случайных ошибок"></nobr> </td> <td style="width:25%;text-align:center">Зашифрованный текст</td> <td><input type="button" value="Расшифровать" title="Расшифровать зашифрованный текст" onClick="perePro2()"></td> </tr> </table> </td> </tr> <tr style="height:100%"> <td style="width:50%"> <textarea id="text1" style="width:100%;height:100%;resize:none" title="Исходный текст"> Мы любим всё — и жар холодных числ, И дар божественных видений Нам внятно всё — и острый галльский смысл, И сумрачный германский гений… («Скифы» А. Блок) </textarea> </td> <td> <textarea id="text2" style="width:100%;height:100%;resize:none" title="Зашифрованный текст"> </textarea> </td> </tr> </table> <div id="panel" style="position:absolute;width:369px;left:3px;top:69px; background-color:#ccc;border-style:solid;border-width:1;border-color:#000; padding:3px" onMouseOver="openPanel()" onMouseOut="closePanel()"> Разбить зашифрованный текст на строки<br> <input type="button" value="по 32 симв." onClick="razbivka(32)"> <input type="button" value="по 64 симв." onClick="razbivka(64)"> <input type="button" value="по 128 симв." onClick="razbivka(128)"> <br> <input type="button" value="Произвольное разбиение" onClick="razbivka(document.getElementById('dlstr').value)"> по <input id="dlstr" type="text" size="4" value="256"> симв. <br> <input type="button" value="Без разбиения" onClick="razbivka(0)"> <br><br> <input type="button" value="ОЧИСТИТЬ ВСЕ ПОЛЯ" onClick="cleaner()" style="width:100%;height:69px"> </div> <table id="NoJS" style="position:absolute;left:0;top:0;width:100%;height:100%"><tr> <td style="background-color:#aaa;text-align:center"> Ваш браузер не поддерживает Javascript, либо эта функция отключена. Без нее работа программы невозможна. Обновите браузер или включите Javascript в его настройках. В случае затруднений обратитесь к опытному пользователю за помощью. </td> </tr></table> </div> <script language="javascript" type="text/javascript"> /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Copyright (C) Paul Johnston 1999 - 2000. * Updated by Greg Holt 2000 - 2001. * See http://pajhome.org.uk/site/legal.html for details. */ /* * Convert a 32-bit number to a hex string with ls-byte first */ var hex_chr = "0123456789abcdef"; function rhex(num) { str = ""; for(j = 0; j <= 3; j++) str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) + hex_chr.charAt((num >> (j * 8)) & 0x0F); return str; } /* * Convert a string to a sequence of 16-word blocks, stored as an array. * Append padding bits and the length, as described in the MD5 standard. */ function str2blks_MD5(str) { nblk = ((str.length + 8) >> 6) + 1; blks = new Array(nblk * 16); for(i = 0; i < nblk * 16; i++) blks[i] = 0; for(i = 0; i < str.length; i++) blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8); blks[i >> 2] |= 0x80 << ((i % 4) * 8); blks[nblk * 16 - 2] = str.length * 8; return blks; } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left */ function rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } /* * These functions implement the basic operation for each round of the * algorithm. */ function cmn(q, a, b, x, s, t) { return add(rol(add(add(a, q), add(x, t)), s), b); } function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t); } function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t); } function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t); } function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Take a string and return the hex representation of its MD5. */ function calcMD5(str) { x = str2blks_MD5(str); a = 1732584193; b = -271733879; c = -1732584194; d = 271733878; for(i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; a = ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = ff(d, a, b, c, x[i+ 1], 12, -389564586); c = ff(c, d, a, b, x[i+ 2], 17, 606105819); b = ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = ff(d, a, b, c, x[i+ 5], 12, 1200080426); c = ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = ff(b, c, d, a, x[i+ 7], 22, -45705983); a = ff(a, b, c, d, x[i+ 8], 7 , 1770035416); d = ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = ff(c, d, a, b, x[i+10], 17, -42063); b = ff(b, c, d, a, x[i+11], 22, -1990404162); a = ff(a, b, c, d, x[i+12], 7 , 1804603682); d = ff(d, a, b, c, x[i+13], 12, -40341101); c = ff(c, d, a, b, x[i+14], 17, -1502002290); b = ff(b, c, d, a, x[i+15], 22, 1236535329); a = gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = gg(c, d, a, b, x[i+11], 14, 643717713); b = gg(b, c, d, a, x[i+ 0], 20, -373897302); a = gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = gg(d, a, b, c, x[i+10], 9 , 38016083); c = gg(c, d, a, b, x[i+15], 14, -660478335); b = gg(b, c, d, a, x[i+ 4], 20, -405537848); a = gg(a, b, c, d, x[i+ 9], 5 , 568446438); d = gg(d, a, b, c, x[i+14], 9 , -1019803690); c = gg(c, d, a, b, x[i+ 3], 14, -187363961); b = gg(b, c, d, a, x[i+ 8], 20, 1163531501); a = gg(a, b, c, d, x[i+13], 5 , -1444681467); d = gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = gg(c, d, a, b, x[i+ 7], 14, 1735328473); b = gg(b, c, d, a, x[i+12], 20, -1926607734); a = hh(a, b, c, d, x[i+ 5], 4 , -378558); d = hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = hh(c, d, a, b, x[i+11], 16, 1839030562); b = hh(b, c, d, a, x[i+14], 23, -35309556); a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = hh(d, a, b, c, x[i+ 4], 11, 1272893353); c = hh(c, d, a, b, x[i+ 7], 16, -155497632); b = hh(b, c, d, a, x[i+10], 23, -1094730640); a = hh(a, b, c, d, x[i+13], 4 , 681279174); d = hh(d, a, b, c, x[i+ 0], 11, -358537222); c = hh(c, d, a, b, x[i+ 3], 16, -722521979); b = hh(b, c, d, a, x[i+ 6], 23, 76029189); a = hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = hh(d, a, b, c, x[i+12], 11, -421815835); c = hh(c, d, a, b, x[i+15], 16, 530742520); b = hh(b, c, d, a, x[i+ 2], 23, -995338651); a = ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = ii(d, a, b, c, x[i+ 7], 10, 1126891415); c = ii(c, d, a, b, x[i+14], 15, -1416354905); b = ii(b, c, d, a, x[i+ 5], 21, -57434055); a = ii(a, b, c, d, x[i+12], 6 , 1700485571); d = ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = ii(c, d, a, b, x[i+10], 15, -1051523); b = ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = ii(a, b, c, d, x[i+ 8], 6 , 1873313359); d = ii(d, a, b, c, x[i+15], 10, -30611744); c = ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = ii(b, c, d, a, x[i+13], 21, 1309151649); a = ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = ii(d, a, b, c, x[i+11], 10, -1120210379); c = ii(c, d, a, b, x[i+ 2], 15, 718787259); b = ii(b, c, d, a, x[i+ 9], 21, -343485551); a = add(a, olda); b = add(b, oldb); c = add(c, oldc); d = add(d, oldd); } return rhex(a) + rhex(b) + rhex(c) + rhex(d); } /* Функция IntToHex возвращает шестнадцатеричные представления целых чисел. Такая стандартная функция есть в языке Delphi. Теперь я написал её аналог и для Javascript. Функция имеет два входных параметра: chi - целое положительное число, kol - длина выходной строки. Пример использования IntToHex(234,4) возвращает '00ea' IntToHex(1234567,10) возвращает '000012d687' IntToHex(234,0) возвращает 'ea' IntToHex(1234567,0) возвращает '12d687' */ function IntToHex(chi,kol){ var chi2=Math.floor(Math.abs(chi)); var mn=1; var k=1; for(var i=chi2;i>15;i=i/16){mn=mn*16;k=k+1;} var he=''; var j='(c)arraylove.narod.ru,2013'; for(i=1;i<=k;i++){ j=Math.floor(chi2/mn); chi2=chi2-(mn*j); switch (j) { case 10: he=he+'a'; break; case 11: he=he+'b'; break; case 12: he=he+'c'; break; case 13: he=he+'d'; break; case 14: he=he+'e'; break; case 15: he=he+'f'; break; default: he=he+j; break; } mn=mn/16; } if(kol!=0){ for(i=1;i<=kol;i++){he='0'+he;} he=he.substr(-kol); } return he; } /* Обратная функция для перевода шестнадцатеричной строковой записи целого числа в числовой формат. Пример использования HexToInt('00eA') возвращает 234 HexToInt('000012d687') возвращает 1234567 HexToInt('FFff') возвращает 65535 */ function HexToInt(he){ var he2=he.toLowerCase(); he2=he2.replace(/[^0-9a-f]/g,''); var le=he2.length; var mn=1; var su=0; var j=le; var ch='(c)arraylove.narod.ru,2013'; for(var i=0;i<le;i++){ j=j-1; ch=he2.substr(j,1); switch (ch) { case 'a': su=su+(mn*10); break; case 'b': su=su+(mn*11); break; case 'c': su=su+(mn*12); break; case 'd': su=su+(mn*13); break; case 'e': su=su+(mn*14); break; case 'f': su=su+(mn*15); break; default: su=su+(mn*ch); break; } mn=mn*16; } return su; } /* Программа синусоидального шифрования сообщений. Посвящается всем спецслужбам мира. ;) */ with(document.getElementById('NoJS')){ style.width='69px'; style.left='-999px'; } document.body.style.overflow='hidden'; function closePanel(){ var width = window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth; le=width-9; le=le+'px'; document.getElementById('panel').style.left=le; } closePanel(); window.onresize=closePanel; function openPanel(){ var width = window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth; le=width-369; le=le+'px'; document.getElementById('panel').style.left=le; } function razbivka(m){ var n='arraylove.narod.ru'+m; n=n.replace(/[^0-9]/g,''); n=0+n; n=1*n; var st=document.getElementById('text2').value; st=st.replace(/[^0-9a-f]/g,''); var L=st.length; var st2='(c)arraylove.narod.ru,2013'; if(n==0){ st2=st; }else{ st2=''; var st3='(c)arraylove.narod.ru,2013'; for(var i=0;i<L;i=i+n){ st3=st.substr(i,n); st2=st2+'\n'+st3; } st2=st2.replace(/^\n/,''); } document.getElementById('text2').value=st2; closePanel(); } function cleaner(){ document.getElementById('text1').value=''; document.getElementById('text2').value=''; document.getElementById('key').value=''; document.getElementById('key2').value=''; document.getElementById('dlstr').value='256'; closePanel(); } function perePro1(){ var st=document.getElementById('text1').value; document.getElementById('text2').value=''; if(st!=''){ var key=document.getElementById('key').value; if(key==document.getElementById('key2').value){ var st2=cipher69690(st,key); document.getElementById('text2').value=st2; }else{ alert('Введенные ключи не совпадают!'); } }else{ alert('Не задан исходный текст.'); } } function perePro2(){ var st=document.getElementById('text2').value; document.getElementById('text1').value=''; var key=document.getElementById('key').value; var st2=cipher6969(st,key); document.getElementById('text1').value=st2; if(st2==''){alert('Введён неверный ключ или зашифрованный текст повреждён.');} } function cipher69690(st1,passwo){ var kA = new Array (); var st2=calcMD5(passwo); kA[0]=HexToInt(st2.substring( 0, 4)); kA[1]=HexToInt(st2.substring( 4, 8)); kA[2]=HexToInt(st2.substring( 8,12)); kA[3]=HexToInt(st2.substring(12,16)); kA[4]=HexToInt(st2.substring(16,20)); kA[5]=HexToInt(st2.substring(20,24)); kA[6]=HexToInt(st2.substring(24,28)); kA[7]=HexToInt(st2.substring(28,32)); var kB = new Array ( 69691, 69697, 86969, 116969, 169691, 169693, 296969, 356969); var kC = new Array (); st2=calcMD5(st1); kC[0]=HexToInt(st2.substring( 0, 4)); kC[1]=HexToInt(st2.substring( 4, 8)); kC[2]=HexToInt(st2.substring( 8,12)); kC[3]=HexToInt(st2.substring(12,16)); kC[4]=HexToInt(st2.substring(16,20)); kC[5]=HexToInt(st2.substring(20,24)); kC[6]=HexToInt(st2.substring(24,28)); kC[7]=HexToInt(st2.substring(28,32)); var L1=st1.length; var plu='(c)arraylove.narod.ru,2013'; var garmo=0; for(var i=0;i<L1;i++){ garmo= kA[0]*Math.sin(kB[0]*i+kC[0])+ kA[1]*Math.sin(kB[1]*i+kC[1])+ kA[2]*Math.sin(kB[2]*i+kC[2])+ kA[3]*Math.sin(kB[3]*i+kC[3])+ kA[4]*Math.sin(kB[4]*i+kC[4])+ kA[5]*Math.sin(kB[5]*i+kC[5])+ kA[6]*Math.sin(kB[6]*i+kC[6])+ kA[7]*Math.sin(kB[7]*i+kC[7]); garmo=Math.round(Math.abs(garmo)); garmo=garmo%65536; plu=st1.charCodeAt(i); plu=(plu+garmo)%65536; plu=IntToHex(plu,4); st2=st2+plu;//+','; } return st2; } function cipher6969(st1,passwo){ var kA = new Array (); var st2=calcMD5(passwo); kA[0]=HexToInt(st2.substring( 0, 4)); kA[1]=HexToInt(st2.substring( 4, 8)); kA[2]=HexToInt(st2.substring( 8,12)); kA[3]=HexToInt(st2.substring(12,16)); kA[4]=HexToInt(st2.substring(16,20)); kA[5]=HexToInt(st2.substring(20,24)); kA[6]=HexToInt(st2.substring(24,28)); kA[7]=HexToInt(st2.substring(28,32)); var kB = new Array ( 69691, 69697, 86969, 116969, 169691, 169693, 296969, 356969); var st15=st1.toLowerCase(); st15=st15.replace(/[^0-9a-f]/g,''); var L15=st15.length; st2=''; if((L15%4==0)&&(L15>32)){ var he1=st15.substring(0,32); var kC = new Array (); kC[0]=HexToInt(he1.substring( 0, 4)); kC[1]=HexToInt(he1.substring( 4, 8)); kC[2]=HexToInt(he1.substring( 8,12)); kC[3]=HexToInt(he1.substring(12,16)); kC[4]=HexToInt(he1.substring(16,20)); kC[5]=HexToInt(he1.substring(20,24)); kC[6]=HexToInt(he1.substring(24,28)); kC[7]=HexToInt(he1.substring(28,32)); var plu='(c)arraylove.narod.ru,2013'; var garmo=0; var t=0; for(var i=32;i<L15;i=i+4){ garmo= kA[0]*Math.sin(kB[0]*t+kC[0])+ kA[1]*Math.sin(kB[1]*t+kC[1])+ kA[2]*Math.sin(kB[2]*t+kC[2])+ kA[3]*Math.sin(kB[3]*t+kC[3])+ kA[4]*Math.sin(kB[4]*t+kC[4])+ kA[5]*Math.sin(kB[5]*t+kC[5])+ kA[6]*Math.sin(kB[6]*t+kC[6])+ kA[7]*Math.sin(kB[7]*t+kC[7]); t=t+1; garmo=Math.round(Math.abs(garmo)); garmo=garmo%65536; plu=st15.substr(i,4); plu=HexToInt(plu); plu=(plu+65536-garmo)%65536; plu=String.fromCharCode(plu); st2=st2+plu; } } if(calcMD5(st2)!=he1){st2='';} return st2; } </script> </body> </html>
Поделиться32019-02-06 11:59:06
Алгоритм синусоидального шифрования Yozhix-6969
Посвящается мировым спецслужбам
КРАТКОЕ ОПИСАНИЕ ПРОГРАММЫ YOZHIX
(ДЛЯ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ)
Чтобы хоть как-то обезопасить свою переписку по открытым каналам сети Интернет, её надо хорошо шифровать. Программы для шифрования часто бывают недоступны сторонам, ведущим переписку, в таком случае очень может помочь программа Yozhix.
Yozhix - это браузерная программа, предназначенная для шифрования сообщений прямо в браузере пользователя. Т.е., имея любой популярный интернет-браузер (FireFox, Chrome, Opera, Netscape Navigator, Internet Explorer и др.), Вы можете шифровать свои сообщения и после размещать их на любом открытом сетевом сервисе. Теперь их сможет прочитать только адресат, знающий ключевое слово (пароль), а не агенты матрицы и админы серверов.
ВНИМАНИЕ! Yozhix - это алгоритм шифрования с закрытым ключом! Это значит, что ключ ни в коем случае не должен пересылаться по сети, чтоб не стать известным посторонним лицам. Ключ можно заранее шёпотом оговорить при личной встрече или использовать в качестве ключа какие-то секретные факты. Например, "пятое слово из нашего любимого стихотворения", но ни в коем случае "номер моего дома" или "твоя фамилия" - это слишком очевидные ключи.
Многие сетевые сервисы не позволяют размещать слишком длинные наборы букв, поэтому в программе предусмотрена возможность разбивки шифровок на короткие строки. Инструмент "Разбить зашифрованный текст на строки" Вы можете найти в боковом выпадающем меню.
И ещё, постарайтесь не переусердствовать с излишней конспирацией. Разговоры о погоде или новых веяниях в мире моды вполне можно вести открытым текстом. Yozhix создан для того чтобы обезопасить передачу конфиденциальных данных или скрыть любовную переписку.
ПОДРОБНОЕ ОПИСАНИЕ АЛГОРИТМА СИНУСОИДАЛЬНОГО ШИФРОВАНИЯ YOZHIX-6969
(ДЛЯ СПЕЦИАЛИСТОВ)
Yozhix-6969 - симметричный метод шифрования, заключающийся в увеличении UTF-кодов шифруемых символов на величины соответствующих значений гармонической функции.
Для описания метода шифрования введём обозначения.
M — количество символов в шифруемом сообщении.
0, 1, ... , N — нумерация символов в сообщении. Здесь N=M-1.
p0, p1, ... , pN — это коды символов исходного текста.
r0, r1, ... , rN — это изменённые коды символов, которые будут записаны в шифровке.
Вычисление изменённых кодов происходит по формулам:
r0=(p0 + round(abs(f(0)))%65536) % 65536,
r1=(p1 + round(abs(f(1)))%65536) % 65536,
...
rN=(pN + round(abs(f(N)))%65536) % 65536.
Здесь "%" — операция арифметическая операция вычисления остатка от целочисленного деления, round(x) — функция вычисления округлённого значения x, abs(x) — вычисление модуля x. Функцию f(x) рассмотрим подробнее, т.к. она является нестандартной жемчужиной всего алгоритма.
Функция f(x) — это "высокочастотная" гармоническая функция, состояшая из 8 волновых составляющих:
f(x)=A0*sin(B0*x+C0)+A1*sin(B1*x+C1)+...+A7*sin(B7*x+C7).
Коэффициенты Ai, Bi, Ci функции f(x) задают её сложность и секретность для оппонента, пытающегося разгадать шифровку. Рассмотрим, каковы значения этих коэффициентов.
Bi — частотные коэффициенты. Эти коэфиициенты не являются секретными. В качестве частотных коэффициентов я взял первые 8 простых чисел, которые содержат в своей записи цифровую последовательность "6969" (отсюда и название алгоритма "Yozhix-6969"). Вот эти коэффициенты: B0=69691, B1=69697, B2=86969, B3=116969, B4=169691, B5=169693, B6=296969, B7=356969.
Ai — амплитудные коэффициенты. Эти коэффициенты являются секретными, т.к. их значения получаются из ключа (секретного слова). Вкратце о вычислении Ai:
1) Вычисляем MD5-образ ключа. Это 16-байтовая последовательность.
2) Полученный MD5 разбиваем на 8 двубайтовых целых чисел.
Это и будут коэффициенты Ai.
Таким образом коэффициенты Ai являются целыми числами, изменяющимися в диапазоне от 0 до 65535.
Пример вычисления Ai.
Пусть ключом является цифровая последовательность "1234".
MD5 ключа: 81dc9bdb52d04dc20036dbd8313ed055
Разбиваем на 2-байтовые целые числа:
81dc --> A0=33244
9bdb --> A1=39899
52d0 --> A2=21200
4dc2 --> A3=19906
0036 --> A4=54
dbd8 --> A5=56280
313e --> A6=12606
d055 --> A7=53333
Ci — фазовые коэффициенты. Эти коэффициенты не являются секретными. Они вычисляются аналогично Ai, но на основе MD5-образа исходного текста. К слову, MD5-код исходного текста открыто записывается в шифровку. Это необходимо для обратной расшифровки и проверки её правильности.
Рассмотрим пример формирования шифрованного сообщения.
Ключ: "1234"
Исходный текст: "Мама мыла раму" (14 символов)
Программа создаёт шифровку:
058612fb51737ad91f285e746d1ae5b9
ea3460a778af882f530679621096a459
5f301aa023951aae2385dd7e
Рассмотрим шифровку подробнее:
058612fb51737ad91f285e746d1ae5b9 - MD5-образ текста "Мама мыла раму"
ea34 - r0 (шестнадцатеричная запись)
60a7 - r1
78af - r2
882f - r3
5306 - r4
7962 - r5
1096 - r6
a459 - r7
5f30 - r8
1aa0 - r9
2395 - r10
1aae - r11
2385 - r12
dd7e - r13
Как видим, первые 32 символа шифровки являются MD5-кодом исходного текста. Остальная часть шифровки отводится под 4-значные 16-теричные записи изменённых кодов.
Остаётся добавить, что процесс шифрования обратим. Расшифровка производится следующим обратным преобразованием:
p0=(r0 + 65536 -round(abs(f(0)))%65536) % 65536,
p1=(r1 + 65536 -round(abs(f(1)))%65536) % 65536,
...
pN=(rN + 65536 -round(abs(f(N)))%65536) % 65536.