Teknik Makale

PDF İmzalama için Saf Pascal NIST Eğri Aritmetiği

HotPDF, PDF için eliptik eğri anahtar anlaşmasını ve imza doğrulamasını saf Object Pascal ile gerçekleştirir; yol üzerinde ne OpenSSL bağlantısı ne de platform kripto sağlayıcısı vardır. Bu beş eğriyi kapsar: NIST asal aileleri için P-256, P-384 ve P-521, ayrıca Montgomery eğrisi anahtar anlaşması için X25519 ve X448. O kodu bağlamak yerine yazmanın nedeni dağıtımdır, saflık değil. Tek bir çalıştırılabilir dosya ve hiçbir kriptografik DLL gönderen bir Delphi ya da Free Pascal uygulamasının yönetecek sürüm kayması, algılanacak platform başına sağlayıcısı ve müşterisi sistem kitaplıklarını yamaladığında değişecek davranışı yoktur

Bedeli, aritmetiğin artık size ait olmasıdır. Büyük tamsayılı modüler çarpma affetmez bir koddur: yayınlanmış test vektörlerine karşı ya bayta özdeş sonuçlar üretir ya da inandırıcı görünen çöp üretir ve bu iki durum arasındaki mesafe tek bir karşılaştırma olabilir. Bu, o karşılaştırmanın öyküsüdür; çünkü hatanın biçimi, cisim aritmetiğinin herhangi bir Pascal portuna geneller

Bir PDF kitaplığının eğri aritmetiğine hiç ihtiyacı olur mu?

İki özellik onu içeri çeker. İlki belgelerin açık anahtarlı şifrelemesidir: ISO 32000 alıcı listesi işleyicisi, adlandırılmış sertifikalar için belge başına bir anahtarı sarmalar ve alıcı bir EC anahtarı taşıdığında sarmalama, RSA anahtar taşıması yerine anahtar anlaşması üzerinden yürür. ECDH olmadan böyle bir belgeyi açmanın yolu yoktur. İkincisi imza doğrulamasıdır. /ByteRange baytları üzerindeki bir ECDSA imzasını doğrulamak, imzalayan eğrisinde bir nokta çarpımı gerektirir ve P-384, P-256'nın hedef değil taban sayıldığı kamu ve nitelikli imza profillerinde yaygındır. HotPDF o çalışmanın sonuçlarını ECDSA ve CMS doğrulama yoluyla ve takılabilir imza sağlayıcı modeliyle açar

HotPDF saf Pascal eğri aritmetiğinin nerede kullanıldığı şeması: alıcı listesi ECDH şifrelemesi ve ByteRange üzerinde ECDSA imza doğrulaması
Anahtar anlaşması, EC ile şifrelenmiş belgeleri adlandırılmış alıcılar için açar; imza doğrulaması ise imzalayan eğrisinde nokta çarpımı gerektirir

CIOS ve sondaki tek çıkarma

Montgomery çarpımı, indirgemenin bir kaydırma olduğu dönüştürülmüş bir alanda çalışarak bölmeyi önler. HotPDF'in kullandığı varyant, Coarsely Integrated Operand Scanning'dir; çarpma ile indirgemeyi limb limb iç içe geçirir, böylece ara değer asla modül genişliği artı bir limbi aşarak büyümez. Döngü gövdesi düpedüz ve test etmesi kolaydır. Kuyruk öyle değildir: iç içe geçmiş geçişlerden sonra akümülatör, modülün iki katına kadar olan aralıkta herhangi bir yerde olabilir; dolayısıyla algoritma, akümülatör asala ancak ve ancak eşit ya da büyükse asalın bir kopyasını kaldıran koşullu bir çıkarma ile biter

İki çok limbli sayıyı karşılaştırmak, borç taşıyarak en anlamlı limbten aşağıya yürümek demektir. Yazmanın bariz yolu, akümülatör limbini modül limbine gelen borcu ekleyerek karşılaştırmaktır. O ifade yanlıştır ve çoğu eğrinin sakladığı bir şekilde yanlıştır

// Yanlış: P[I] $FFFFFFFFFFFFFFFF olduğunda P[I] + Borrow taşabilir
if T[I] < P[I] + Borrow then
begin
  Borrow := 1;
  Break;
end;

// Doğru: hiçbir limbe ekleme yapmadan karşılaştır
if (T[I] < P[I]) or ((T[I] = P[I]) and (Borrow = 1)) then
begin
  Borrow := 1;
  Break;
end;

Bir borç taşması gerçekte neye benzer?

Üretim dışında her yerde çalışan bir eğri gibi görünür. P-384 ile P-521'in asalları tamamen birlerden oluşan limbler içerir; dolayısıyla P[I], $FFFFFFFFFFFFFFFF'e eşittir. Buna gelen bir borcunu ekleyin ve 64 bitlik işaretsiz bir değer sıfıra taşar. Karşılaştırma sonra akümülatör limbinin sıfırdan küçük olup olmadığını sorar, küçük olmadığına karar verir ve borç gerekmediği sonucuna varır. Sonucun bir limb'i bir kadar yanlıştır

Montgomery indirgeme borç taşıma şeması; HotPDF P-384 aritmetiğinde yanlış limb karşılaştırmasını doğru borç yayılımıyla karşıtlar
Borcu tamamen birlerden oluşan bir limbe eklemek sıfıra taşar; böylece P-384 ile P-521 çıkarma yapmazken P-256 kusuru saklar

P-256 kaçar, çünkü limblerinin hiçbiri tamamen birlerden oluşmaz; dolayısıyla toplama hiç taşmaz ve hatalı ifade tesadüfen doğrusuyla örtüşür. Bir test takımı için en kötü olası sonuç budur: en çok test edilen eğri geçer, daha az test edilenler işlenen değerlerine bağlı olarak aralıklı başarısız olur ve hata, tamamen geçerli belgelerde "geçersiz imza" doğrulama sonucu olarak yüzeye çıkar. HotPDF, tam da bu nedenle P-384 üzerinde açık bir kapı taşıyordu; aritmetik referans vektörlerine karşı kanıtlanana dek yanlış bir cevap yerine kullanılamaz durumu döndürüyordu

Hata gerçekte nasıl bulundu

Kodu okuyarak değil. Verimli dizi mekanikti ve yeniden kullanılabilir. Birincisi, sabitleri eliyin: p, R ve R^2'nin her limbi bağımsız yeniden üretildi ve limb limb karşılaştırıldı; bu, eğri hatalarının en yaygın tek kaynağını elemeye yeter. İkincisi, API'yi değil aritmetiği ölçümleyin: geçici bir döküm yordamı, bilinen bir nokta için R^2'nin, x^3'ün ve y^2'nin Montgomery çarpımının ara değerlerini yazdı; böylece bağımsız hesaplanmış gerçekle denetlenebildiler

O karşılaştırma doğrudan suçluyu işaret etti. x zinciri baştan sona doğrudu; oysa y^2, tam olarak tek limpte tam olarak bir farklıydı. Tek limbli birlik bir fark ne bir çarpma hatası ne bir elde yayılımı hatası ne de bir sabit hatasıdır; borç zinciri hatasıdır ve yordamdaki tek borç zinciri sondaki koşullu çıkarmadır. Bir ayrıntı bunu neredeyse rayından çıkardı: döküm için kullanılan referans sabitinin kendisi ilk denemede yanlış bayt sırasıyla yazılmıştı; bu, y değerinde bir uyuşmazlık üretti ve kısa süre için var olmayan ikinci bir kusur iması verdi. Kodunuzu suçlaması için ona güvenmeden önce zemin gerçekinizin bayt sırasını doğrulayın

HotPDF eğri hatasının sabitleri yeniden üreterek, Montgomery ara değerlerini dökerek ve ayna gerçeğiyle diff alarak bulunması akış şeması
Tam olarak birlik tek limbli bir fark doğrudan yordamdaki tek borç zincirini işaret etti ve baytları ters yazılmış bir referans avı neredeyse yanlış yöne çekti

Aynı yordamdaki komşu tuzaklar

O karşılaştırmanın birkaç satır ötesinde üç hata modu daha yaşar ve üçü de geliştirme boyunca bir noktada canlıydı

// 1. Akümülatörün modül genişliğinin bir üstünde bir limb değeri vardır.
//    Yalnızca alt L limb değerini karşılaştırmak, T'nin tam olarak
//    p artı 2^(64*L)'ye eşit olduğu durumu kaçırır; 2p, P-256 için
//    2^256'yı ve P-384 için 2^384'ü aştığından bu, rastgele girdilerin
//    anlamlı bir payı için olur
if (T[L] <> 0) or NotLessThanModulus(T, P, L) then
  SubtractModulus(T, P, L);

// 2. Genel amaçlı çok limbli bir çıkarma aynı taşma riskini taşır: Y[I]
//    $FFFFFFFFFFFFFFFF olduğunda Y[I] + Borrow sıfıra taşar ve borç,
//    temizlenmek yerine sonraki limbe aktarılmalıdır
Diff := X[I] - Y[I] - Borrow;
NextBorrow := Ord((X[I] < Y[I]) or ((X[I] = Y[I]) and (Borrow = 1)));

Üçüncüsü kod değil, kaynaklıktır. P-521'in asalı başlangıçta 131 yerine 130 onaltılık basamakla, bir F eksiğiyle aktarıldı ve Montgomery sabitleri sonra o yanlış asaldan hesaplandı; böylece sabitler kendi içinde tutarlı ve birlikte yanlıştı. Eğri parametreleri türetilmelidir, asla yazılmamalıdır: R'yi, gerçekten kullandığınız asaldan (1 shl (64 * L)) mod p olarak hesaplayın, sonra R * R mod p değerini R^2 sabitinizin iddia ettiği değerle çapraz denetleyin. Birbirine uyan bir sabit çifti, ikisi hakkında da hiçbir şey kanıtlamaz

Tek bir eğrinin ötesine ölçeklenen doğrulama stratejisi

X25519 ile X448'i yönetilebilir kılan teknik, sınırsız tamsayılı bir dilde bir ayna uygulaması yazmak ve Pascal denetim akışını satır satır ona aktarmaktı. Ayna doğru cevabı üretirken Pascal üretmediğinde kusur bir aktarım hatasıdır ve her iki uygulamada da aynı ara değeri yoklamak onu saniyeler içinde bulur. Üç klasik RFC 7748 merdiven hatasının üçü de böyle yakalandı: ikinci satırı çoktan değişmiş değeri yeniden kullanan sabit zamanlı bir takas, z'yi X'e çarpmak yerine eksi birinci kuvvetine döndüren sondaki ters alma ve yarım sözcük çarpımlarını bitsel or ile birleştirip eldeyi kaybeden küçük sabitli bir çarpma

Test malzemesi için vektörleri metin olarak değil bayt olarak alın. Özel bir anahtarı bir metin deseniyle çıkarmak, doğru bir uygulamanın tamamen çıkarma adımında yaşayan bir bayt kayması hatasıyla suçlanmasına yol açar. Onaltılıkları DER kodlamasından bilinen ofsetlerde dilimleyin ve bayt dizilerini karşılaştırın

Borç zinciri düzeltildikten sonra beş eğrinin tamamı yayınlanmış referans vektörleriyle bayt bayt örtüşüyor ve HotPDF artık hiçbirini kapı ile sınırlamıyor. Sertifika tabanlı imzalama ya da alıcı listesi şifrelemesi entegre ediyorsanız pratik çıkarım şudur: eğri seçimi artık bir yetenek sorusu değil politika kararıdır; imzalama tarafının profilleri ve bayt sırası tuzakları PAdES imzalama kılavuzunda kapsanır. Bileşen ayrıntıları ve desteklenen algoritma matrisi HotPDF Delphi PDF component ürün sayfasındadır