A HotPDF elliptikus görbe kulcsmegállapodást és aláírás-ellenőrzést végez PDF-hez tiszta Object Pascalban, OpenSSL-kötés nélkül és platformtitkosítási szolgáltató nélkül az útban. Ez öt görbét fed le: P-256, P-384 és P-521 a NIST prímcsaládokhoz, plusz X25519 és X448 Montgomery-görbe kulcsmegállapodáshoz. Az ok, hogy ezt a kódot írjuk meg linkelés helyett, a telepítés, nem a tisztaság. Egy Delphi vagy Free Pascal alkalmazás, amely egyetlen végrehajtható fájlt szállít titkosítási DLL nélkül, nem kezel verzióeltolódást, nem észlel platformonkénti szolgáltatót, és semmi sem változtatja meg a viselkedését, amikor egy ügyfél kijavítja a rendszertárait
Az ára az, hogy mostantól Ön birtokolja az aritmetikát. A nagyegész moduláris szorzás kíméletlen kód: vagy bájtonként azonos eredményt ad a publikált tesztvektorokkal szemben, vagy hihetőnek látszó szemétprodukciót ad, és a két állapot közötti távolság egyetlen összehasonlítás lehet. Ez az összehasonlítás története, mert a hiba alakja bármely testi aritmetika Pascal-portolására általánosít
Miért van egy PDF-könyvtárnak egyáltalán görbearitmetikára szüksége?
Két funkció húzza be. Az első a dokumentumok nyilvános kulcsú titkosítása: az ISO 32000 címzettlista-kezelő dokumentumonkénti kulcsot csomagol be megnevezett tanúsítványokhoz, és amikor egy címzett EC kulcsot birtokol, a becsomagolás kulcsmegállapodáson át fut RSA kulcsszállítás helyett. ECDH nélkül nincs mód egy ilyen dokumentum megnyitására. A második az aláírásérvényesítés. Egy ECDSA aláírás ellenőrzése a /ByteRange bájtok felett pontszorzást igényel az aláíró görbén, és a P-384 gyakori kormányzati és minősített aláírási profilokban, ahol a P-256 padlónak számít, nem célnak. A HotPDF ennek a munkának az eredményeit a ECDSA és CMS ellenőrzési útvonalon és a cserélhető aláírásszolgáltató modellen át teszi elérhetővé
CIOS és a végén álló egyetlen kivonás
A Montgomery-szorzás elkerüli az osztást egy átalakított tartományban dolgozva, ahol a redukció léptetés. A HotPDF által használt változat a Coarsely Integrated Operand Scanning, amely limbenként összeszövi a szorzást és a redukciót, hogy a köztes érték soha ne nőjön a modulus szélessége plusz egy limb fölé. A ciklustörzs egyenes és könnyen tesztelhető. A farok nem az: az összefonódott menetek után az akkumulátor a modulus kétszereséig terjedő tartomány bárhol lehet, tehát az algoritmus feltételes kivonással ér véget, amely a prím egy példányát távolítja el akkor és csak akkor, ha az akkumulátor nagyobb vagy egyenlő annál
Két többlimbes szám összehasonlítása azt jelenti, hogy a legszignifikánsabb limbtől lefelé sétálunk kölcsönt cipelve. A nyilvánvaló írásmód az, hogy az akkumulátor limbet a modulus limbjéhez plusz a beérkező kölcönhöz hasonlítjuk. Az a kifejezés téves, és úgy téves, hogy a legtöbb görbe elrejti
// Rossz: a P[I] + Borrow körbefordulhat, amikor P[I] értéke $FFFFFFFFFFFFFFFF
if T[I] < P[I] + Borrow then
begin
Borrow := 1;
Break;
end;
// Helyes: összehasonlítás limbhez adás nélkül
if (T[I] < P[I]) or ((T[I] = P[I]) and (Borrow = 1)) then
begin
Borrow := 1;
Break;
end;
Milyen valójában egy kölcsön-körbefordulás?
Úgy néz ki, mint egy görbe, amely mindenhol működik, kivéve a termelésben. A P-384 és P-521 prímjei teljesen egyesekből álló limbekeket tartalmaznak, tehát a P[I] egyenlő $FFFFFFFFFFFFFFFF-vel. Adja hozzá az egyes beérkező kölcsönt ahhoz, és egy 64 bites előjel nélküli nullára fordul körbe. Az összehasonlítás ezután azt kérdezi, hogy az akkumulátor limbje kisebb-e nullánál, úgy dönt, hogy nem, és arra a következtetésre jut, hogy nincs szükség kölcsönre. Az eredmény egy limbje eggyel eltér
A P-256 megmenekül, mert egyik limbje sem minden-egyes, tehát az adás soha nem túlcsordul, és a hibás kifejezés éppen egyetért a helyessel. Ez a legrosszabb lehetséges kimenet egy tesztcsomag számára: a legtöbbet tesztelt görbe átmenekül, a kevésbé teszteltek operandusértékektől függően időszakosan elbuknak, és a hiba érvénytelen aláírás ellenőrzési eredményként mutatkozik meg tökéletesen érvényes dokumentumokon. A HotPDF emiatt explicit kaput hordozott a P-384-en, elérhetetlen státuszt visszaadva rossz válasz helyett, amíg az aritmetika referencia-vektorokkal szemben be nem bizonyosodott
Hogyan került valójában felkutatásra a hiba
Nem a kód olvasásával. A termékeny sorrend mechanikus volt, és újrahasznosítható. Először a konstansok kiiktatása: a p, R és R^2 minden limbje egymástól függetlenül újratermelődött, és limbenként összevetett, ami kizárja a görbehibák leggyakoribb egyetlen forrását. Másodszor az aritmetika műszerezése az API helyett: egy ideiglenes dump eljárás kinyomtatta a Montgomery-szorzás köztes értékeit a R^2-re, a x^3-ra és a y^2-re egy ismert ponthoz, hogy függetlenül számolt igazsággal lehessen őket ellenőrizni
Az az összehasonlítás egyenesen a tettesre mutatott. Az x lánc végtől végig helyes volt, míg a y^2 pontosan egy limbben pontosan eggyel eltért. Egylimbes egységnyi eltérés nem szorzási hiba, nem átvitelterjesztési hiba, nem konstanshiba; kölcsönlánc-hiba, és a rutin egyetlen kölcsönlánca a végső feltételes kivonás. Egy részlet majdnem kisiklatta ezt: a dumpra használt referencia-konstans maga is rossz bájtsorrendben íródott az első próbálkozáskor, ami eltérést produkált a y értékben, és rövid időre második, nem létező hibát sugallt. Ellenőrizze az igazságforrása bájtsorrendjét, mielőtt megbízik benne, hogy vádolja a kódját
A szomszédos csapdák ugyanabban a rutinban
Három további hibamód lakik néhány sorra attól az összehasonlítástól, és mindhárom élt valamikor a fejlesztés alatt
// 1. Az akkumulátornak egy limbje van a modulus szélessége felett. Csak
// az alsó L limb összehasonlítása kihagyja azt az esetet, amikor T
// pontosan p plusz 2^(64*L), ami a véletlen bemenetek érdemi része
// esetén előfordul, mert a 2p meghaladja a 2^256-ot P-256 esetén és
// a 2^384-et P-384 esetén
if (T[L] <> 0) or NotLessThanModulus(T, P, L) then
SubtractModulus(T, P, L);
// 2. Egy általános többlimbes kivonás ugyanazt a körbefordulási veszélyt
// hordozza: amikor Y[I] értéke $FFFFFFFFFFFFFFFF, a Y[I] + Borrow
// nullára fordul körbe, és a kölcsönnek a következő limbbe kell
// átmennie, nem pedig törlődnie
Diff := X[I] - Y[I] - Borrow;
NextBorrow := Ord((X[I] < Y[I]) or ((X[I] = Y[I]) and (Borrow = 1)));
A harmadik nem kód, hanem származás. A P-521 prímjét kezdetben 130 hexadecimális számjeggyel írták át 131 helyett, egy F-fel rövidebben, és a Montgomery-konstansokat aztán abból a rossz prímből számolták, tehát a konstansok önkonzisztensek és együttesen tévesek voltak. A görbeparamétereket le kell vezetni, soha nem begépelni: számolja a R-t úgy, mint (1 shl (64 * L)) mod p abból a prímből, amelyet valójában használ, majd keresztellenőrizze a R * R mod p-t azzal az értékkel, amelyet a R^2 konstansa állít. A konstanspáros, amely egymással egyetért, semmiről sem bizonyít
Egyetlen görbén túl skálázódó ellenőrzési stratégia
A technika, amely az X25519-et és X448-at kezelhetővé tette, tükörimplementáció írása volt egy korlátlan egészekkel dolgozó nyelven, és a Pascal vezérlésfolyamatának soronkénti átírása bele. Amikor a tükör a helyes választ adja, és a Pascal nem, a hiba átírási baklövés, és ugyanazon köztes érték megvizsgálása mindkét implementációban másodpercek alatt megtalálja. Mindhárom klasszikus RFC 7748-létra hiba így került elő: egy konstans időű csere, amelynek második sora az már kicserélt értéket használta újra, egy végső inverzió, amely a z-t mínusz egyedik hatványra emelte ahelyett, hogy a X-be szorozta volna, és egy kis-konstansos szorzás, amely félszavas szorzatokat bitenkénti vagy kapcsolással rakott össze, és elvesztette az átvitelt
Tesztanyaghoz a vektorokat bájtként vegye, ne szövegként. Egy privát kulcs kinyerése szövegmintával az oka annak, hogy egy helyes implementációt vádolnak eggyel-eltérő-bájt hibával, amely teljes egészében a kinyerési lépésben lakik. Vágja ki a hexet a DER kódolásból ismert offseteken, és bájttömböket hasonlítson össze
A kölcsönlánc javításával mind az öt görbe bájtonként egyezik a publikált referencia-vektorokkal, és a HotPDF egyiket sem kapuzza többé. Ha tanúsítványalapú aláírást vagy címzettlista-titkosítást integrál, a gyakorlati tanulság az, hogy a görbeválasztás mostantól politikai döntés, nem képességkérdés; az aláíró oldal profiljait és bájtsorrend-buktatóit a PAdES aláírási útmutató tárgyalja. A komponens részletei és a támogatott algoritmusmátrix a HotPDF Delphi PDF component terméklapon találhatók