HMAC üreteci

Bir mesaj ve anahtardan HMAC-SHA-1, SHA-256, SHA-384 ve SHA-512 hesaplar ve verilen bir imzanın hangisinden geldiğini belirler.

Mesaj
HMAC-SHA-1
HMAC-SHA-256
HMAC-SHA-384
HMAC-SHA-512

İmzaları hesaplamak için bir anahtar girin.

Bu araç ne yapar

HMAC, bir mesajı ve paylaşılan bir sırrı kısa bir imzaya dönüştürür. Aynı sırra sahip herkes onu yeniden hesaplayabilir ve mesajın değişmeden geldiğini ve sırrı da bilen birinden geldiğini görebilir. Bu araç dört yaygın varyantı aynı anda hesaplar ve — size gönderilen bir imza verildiğinde — onu hangisinin ürettiğini söyler.

O ikinci yön genellikle insanların geldiği nedendir. Bir webhook doğrulamada başarısız oluyordur ve soru gerçekte «bu imza geçerli mi» değil, «gönderenden farklı yaptığım birkaç makul şeyden hangisi» sorusudur. Yapıştırılan bir imzanın önündeki sha256= biçimindeki önek tanınır ve atılır, böylece başlık değeri geldiği gibi yapıştırılabilir.

Bunun ters gittiği yer anahtardır

HMAC baytları baytlarla imzalar. Mesaj genellikle apaçıktır — ham istek gövdesi — ama anahtar neredeyse hiçbir zaman değildir, çünkü bir sır bir dize olarak gelir ve bir dize, onu nasıl okuyacağınıza karar verene dek bayt değildir:

a3f2   as text     4 bytes   61 33 66 32
a3f2   as hex      2 bytes   a3 f2

Her iki okuma da meşrudur, her ikisi de kusursuzca iyi biçimli bir imza üretir ve iki imzanın hiçbir ortak yanı yoktur. Sizi hiçbir şey uyarmaz: hata yok, uzunluk şikâyeti yok, yalnızca gönderenin hesapladığıyla eşleşmeyen bir değer. Buradaki anahtar kodlamasının bir tahmin değil, görünür bir seçim olmasının nedeni budur — bir imza eşleşmediğinde çevrilecek ilk şey budur.

Kaba bir kılavuz olarak: whsec_ gibi bir öneki ya da karışık büyük/küçük harf ve rakam dizisi olan bir sır normalde metin olarak düşünülür; yalnızca 0-9 ve a-f kullanan tam olarak 32 ya da 64 karakterlik bir dize genellikle hex’tir; ve = ile biten biri neredeyse kesinlikle Base64’tür. Ama biçime değil, gönderenin belgelerine bakın, çünkü biçim kanıt değildir.

Mesaj tam baytlar olmalıdır

Bir uyumsuzluğun diğer yarısı mesajdır. HMAC baytlar üzerinden tanımlanır; bu yüzden baytları değiştiren her şey imzayı tümüyle değiştirir — kısmi puan ve ıskalanmış yakın yoktur.

  • JSON’u yeniden serileştirmek. Bir gövdeyi ayrıştırıp yeniden dizeye çevirmek anahtarları yeniden sıralayabilir, boşluğu değiştirebilir ya da sayıları normalleştirebilir. Ham gövdeyi aldığınız gibi imzalayın ve doğrulayın, asla onun gidip gelmiş bir kopyasını değil.
  • Sondaki bir satır sonu. Bazı araçlar gövdeyi bir dosyaya kaydettiğinizde bir tane ekler; o bir bayttır ve her şeyi değiştirir.
  • Karakter kodlaması. ASCII olmayan metin içeren bir gövdenin, iki tarafın da kullandığı aynı kodlamayla okunması gerekir — pratikte UTF-8.
  • Sıkıştırma ya da ara katman. İşleyicinizin önünde bir şey gövdeyi açıyor ya da yeniden yazıyorsa, bu olduktan sonra değil, önce doğrulayın.

Birçok sağlayıcı gövdeyi de yalnız başına imzalamaz. Stripe, bir nokta ile birleştirilmiş bir zaman damgasını ve gövdeyi imzalar; AWS, yöntem, yol, başlıklar ve yükün bir hash’inden kurulan kanonik bir isteği imzalar. Doğrulama düz gövdeye karşı başarısız olursa, imzalanan dize muhtemelen düz gövde değildir — bu, gönderen tarafında belgelenir ve daha ileri hata ayıklamadan önce okumaya değer.

SHA-1 neden burada sunuluyor da hash aracında sunulmuyor

Hash aracı SHA-1’i bozuk olarak işaretler. Bu araç, HMAC-SHA-1’i uyarısız listeler ve bu bir gözden kaçma değil, bilinçlidir.

SHA-1, imzalar ve sertifikalar için kullanılamaz, çünkü çakışmalar oluşturulabilir: iki farklı belge bir özeti paylaşacak şekilde yapılabilir. HMAC bu özelliğe bağlı değildir. Güvenliği gizli anahtara dayanır ve yapı — mesajı iki kez, anahtar her ikisinde de karıştırılmış olarak hash’lemek — altta yatan hash çakışmaya zayıf olduğunda bile ayakta kalır. HMAC-SHA-1 sağlam kalır ve hâlâ OAuth 1.0a ile eski AWS imzalamasının kullandığı şeydir; bu yüzden onu hesaplamayı reddeden bir araç yalnızca daha az yararlı olurdu, daha güvenli olmadan.

Yeni herhangi bir şey için SHA-256 mantıklı varsayılandır. Daha uzun özetler burada anlamlı biçimde daha güçlü değildir — güvenlik tavanı özet uzunluğu değil, anahtardır — bu yüzden SHA-384 ve SHA-512, yalnızca birlikte çalışmanız gereken bir şey onları istediğinde seçmeye değer.

İmzaları güvenle karşılaştırma

Bu sayfa sıradan bir dize karşılaştırmasıyla karşılaştırır; bu burada sorun değildir: anahtarı kendiniz tutuyorsunuz, dolayısıyla sızacak bir şey yoktur. Gelen bir isteği doğrulayan bir sunucuda ise sorunludur. Sıradan bir karşılaştırma ilk farklı baytta durur; böylece aldığı süre bir tahminin ne kadarının doğru olduğunu açığa çıkarır ve çok istek gönderebilen bir saldırgan geçerli bir imzayı bayt bayt geri elde edebilir.

Platformunuzun sağladığı sabit-zamanlı karşılaştırmayı — Node’da crypto.timingSafeEqual, Python’da hmac.compare_digest, PHP’de hash_equals — hex dizeleri üzerinde değil, ham baytlar üzerinde kullanın. Bununla birlikte, istekte adlandırılmış bir algoritmaya güvenmek yerine kendi hesapladığınız bir imzaya karşı karşılaştırın ve zaman damgası şimdiye çok uzak olan bir mesajı reddedin; böylece eski geçerli bir imza yeniden oynatılamaz.

HMAC bir hash değildir ve bir imza değildir

Burada üç şey karıştırılır ve fark, sonradan neyi öne sürebileceğiniz için önemlidir:

  • Bir hash bir mesaj alır ve bir özet üretir. Herkes onu hesaplayabilir; bu yüzden mesajın kazara değişmediğini kanıtlar — belirli birinden geldiğini değil.
  • Bir HMAC bir mesaj ve paylaşılan bir sır alır. Her iki taraf da aynı anahtarı tutar; bu yüzden gönderenin sırrı bildiğini kanıtlar. Hangi tarafın gönderdiğini kanıtlayamaz, çünkü ikisi de onu üretmiş olabilir.
  • Bir imza, yalnızca gönderenin tuttuğu bir özel anahtar ve herkesin doğrulayabileceği bir genel anahtar kullanır. İnkâr edilemezliği veren budur: gönderen sonradan onu inkâr edemez.

Yani HMAC, zaten bir sır paylaşan iki sistem arasında doğru araçtır — webhook’lar, dahili API’ler, oturum token’ları — ve bir şeyi kimin gönderdiğini üçüncü bir tarafa kanıtlamanız gerektiğinde yanlış olandır. Ayrıca unutmayın ki kimlik doğrular ama gizlemez: mesaj açık olarak yolculuk eder ve HMAC gizlilik hakkında hiçbir şey söylemez.

Bir Stripe webhook imzasını doğrulama

Stripe, burada yapıştırmakla bitmeyen tek tariftir ve genellikle insanların buraya gelmeden önce zaten denemiş olduğudur. Stripe-Signature başlığı bir imza değil, virgülle ayrılmış ögelerden oluşan bir listedir ve Stripe’ın imzaladığı dize istek gövdesinin kendisi değildir. Başlığı satırlara bölen, okunurluk için Stripe’ın kendi belgeleridir; gerçek bir başlık tek satır olarak gelir.

Stripe-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
  • Mesaj: t= değeri, sonra bir nokta, sonra ham istek gövdesi tam olarak geldiği gibi. Yukarıdaki başlık için o dize 1492774577. ile başlar ve gövde hemen ardından gelir. Stripe buna imzalanmış yük der ve bir Stripe imzasının gövdeyle yalnız başına asla eşleşmemesinin bütün nedeni budur.
  • Anahtar: yalnızca o uç noktanın imzalama sırrı, whsec_ öneki dahil olmak üzere tam olarak. Bu sizin API anahtarınız değildir ve başka bir uç noktanın sırrı değildir — iki kez kaydedilmiş aynı URL’nin iki sırrı olur.
  • Anahtar kodlaması: Metin. Bir imzalama sırrı Stripe’ın seçtiği bir dizedir ve rastgele görünse de ne hex ne de Base64’tür; ikisinden biri olarak okumak başka baytlar ve hiçbir şeyle eşleşmeyen bir imza verir.
  • Kontrol edilecek imza: başlığın tamamı değil, yalnızca v1 ögesi. v1= olduğu gibi yapıştırılabilir, çünkü o etiket tam olarak sha256= gibi atılır — ama başlığın tamamı yapıştırılamaz, çünkü baştaki t= etiket sanılır ve ardından geleni hiç imza değildir.

Başka bir yeri kurcalamadan önce bu başlık hakkında bilmeye değer üç şey daha var. v1 dışındaki her şemayı yok sayın: test olaylarındaki v0 ögesi bilinçli olarak gerçek bir imza değildir ve geri kalanını yok saymak, size daha zayıf bir şemanın dayatılmasını tam olarak engelleyen şeydir. Bir uç noktanın sırrı değiştirilirken ikisi de bir güne kadar geçerli kalır ve başlık her sır için bir v1 ögesi taşır; bunlardan yalnızca biri eşleşecektir. Ve her teslim denemesi yeniden imzalanır, dolayısıyla yeni bir deneme ilkinin imzasını taşımaz — imzalanan dizenin içindeki zaman damgası, eski bir imzayı reddetmeyi bir jest değil gerçek bir savunma yapan şeydir de, çünkü imzayı bozmadan onu değiştirmek olanaksızdır.

Bir GitHub webhook imzasını doğrulama

GitHub, bu aracın çevresinde kurulduğu yapıştırmadır ve burada baştan sona kontrol edebileceğiniz tek tariftir, çünkü GitHub çözülmüş bir örnek yayımlar. İmza, X-Hub-Signature-256 başlığında sha256= etiketi ve ardından bir hex özeti olarak gelir; bu etiket burada tanınıp atılır, dolayısıyla başlık değeri tam olarak geldiği gibi girer.

X-Hub-Signature-256:
sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17
  • Mesaj: ham istek gövdesi, bayt bayt. GitHub’ın yayımladığı örnek Hello, World! gövdesini imzalar ve ardından hiçbir şey yoktur — sonda satır sonu da yok.
  • Anahtar: webhook’un ayarlarına yazdığınız sır, tam olarak yazdığınız gibi. Yayımlanan örnek It's a Secret to Everybody kullanır.
  • Anahtar kodlaması: Metin. Bir GitHub sırrı sizin seçtiğiniz bir dizedir, dolayısıyla asla hex değildir — yalnızca hex rakamlarından oluşan bir sır bile yazdığınız karakterler olarak okunur.
  • Kontrol edilecek imza: sha256= dahil başlık değerinin tamamı. Hex büyük/küçük harfe bakılmaksızın karşılaştırılır, dolayısıyla günlüklerinizin onu hangi biçimde yazdığı önemli değildir.

Bu üç değer birlikte var olan en hızlı sağlık kontrolüdür: onları yapıştırın ve bu sayfa hex olarak HMAC-SHA-256 eşleşmesi bildirir; bu da hesaplayıcının ve tarifi okuyuşunuzun ikisinin de doğru olduğunu, ikisini de gerçek bir teslimde denemeden önce söyler. GitHub ayrıca daha eski bir başlık gönderir, X-Hub-Signature: aynı gövde üzerinde HMAC-SHA-1’dir ve yalnızca eski uyumluluk için korunur. Bu sayfa dört özeti aynı anda hesapladığı için, hangisinden geldiğini söylemenize gerek kalmadan iki başlıktan herhangi birinden gelen bir imza tanınır. Kurtaramadığı tek şey, GitHub’ın gönderdiği baytlardan başka bir şey olarak gelmiş bir gövdedir — yükler ASCII dışında karakterler taşıyabilir ve iki tarafın da onları UTF-8 olarak okuması gerekir.

Bir Shopify webhook imzasını doğrulama

Shopify özetini hex değil Base64 olarak yazar ve burada önemli olan tek fark budur: aynı 32 bayt, tek bir eşittir işaretiyle biten 44 karaktere dönüşür ve o karakter bir etiket değil dolgudur, dolayısıyla önünden hiçbir şey kesilmez.

X-Shopify-Hmac-SHA256:
dXEH6g6yUJ/CESIczphLijdXC211hsIsRvQ3nIsEPhc=
  • Mesaj: teslim edildiği gibi ham istek gövdesi, bayt bayt. Shopify’ın kendi uyarısı gövdeyi ayrıştıran ara katman hakkındadır — önce doğrulayın, sonra ayrıştırın; çünkü gövdeyi bir nesneye çevirmiş bir ayrıştırıcı baytları çöpe atmıştır.
  • Anahtar: webhook’un ait olduğu uygulamanın istemci sırrı. Onun erişim token’ı değil ve aynı paneldeki yanındaki API anahtarı da değil.
  • Anahtar kodlaması: Metin. Diğer ikisinde olduğu gibi, sır baytların bir kodlaması değil bir dizedir.
  • Kontrol edilecek imza: başlık değerinin tamamı. Olduğu gibi yapıştırılır ve her özete karşı hem hex hem Base64 denendiği için, bu sayfanın bildirdiği kodlama, gönderenin onu hangi yazımla yazdığının cevabının kendisidir.

Yukarıdaki bloktaki değer biçimi göstermek için oradadır: GitHub örneğindeki aynı 32 bayttır, hex yerine Base64 olarak yazılmıştır. Bunları yan yana görmeye değer, çünkü iki başlık arasındaki farkın bütün içeriği budur — bir özet, iki yazım — ve bu sayfanın size yalnızca bir şeyin eşleştiğini söylemek yerine algoritmanın yanında kodlamayı da anmasının nedeni de budur.

Sıkça sorulan sorular

İmzam eşleşmiyor. İlk olarak neyi kontrol ederim?
Anahtar kodlamasını, sonra mesaj baytlarını. Hex’e benzeyen bir sır çoğu zaman metin değil hex olarak düşünülmüştür ve ikisi de her iki durumda hata olmadan tümüyle farklı imzalar üretir. Ondan sonra, ham gövdeyi onun yeniden serileştirilmiş bir kopyası yerine tam olarak alındığı gibi imzaladığınızdan emin olun.
Hash aracı SHA-1’in bozuk olduğunu söylerken neden burada sunuluyor?
Çünkü HMAC, SHA-1’in yitirdiği özellik olan çakışma direncine dayanmaz. Güvenliği anahtardan gelir. HMAC-SHA-1 hâlâ sağlamdır ve hâlâ OAuth 1.0a ile eski AWS imzalaması tarafından kullanılır, ama yeni herhangi bir şey için doğru varsayılan SHA-256’dır.
Daha uzun bir özet daha mı güvenli?
Anlamlı biçimde değil. Bir HMAC’in gücü, özet uzunluğuyla değil, sırla sınırlanır; bu yüzden SHA-512, SHA-256’dan dört kat daha iyi değildir. Karşı tarafın beklediğini seçin.
HMAC ile bir dijital imza arasındaki fark nedir?
HMAC, her iki tarafın da bildiği tek bir sır kullanır; bu yüzden gönderenin sırrı bildiğini kanıtlar ama hangi tarafın gönderdiğini değil. Bir dijital imza, yalnızca gönderenin tuttuğu bir özel anahtar kullanır; böylece üçüncü bir taraf onu doğrulayabilir ve gönderen onu inkâr edemez. O son özelliğe ihtiyacınız varsa HMAC yanlış araçtır.
İmzaları === ile karşılaştırmalı mıyım?
Bir sunucuda değil. Sıradan bir karşılaştırma baytlar farklılaşır farklılaşmaz döner ve o zamanlama, tahmin edilen bir imzanın ne kadarının doğru olduğunu sızdırır. Platformunuzun sabit-zamanlı karşılaştırmasını ham baytlar üzerinde kullanın. Bu sayfada önemli değildir, çünkü anahtarı zaten tutuyorsunuz.
Anahtarım herhangi bir yere gönderiliyor mu?
Hayır. Her şey tarayıcınızda Web Crypto API ile hesaplanır; mesaj ve anahtar cihazınızdan asla çıkmaz.
Bir Stripe webhook imzasını nasıl doğrularım?
Üç şeyi tek bir dizede birleştirin — başlığın t= ögesindeki zaman damgası, bir nokta ve ham istek gövdesi — ve bunu uç noktanın imzalama sırrıyla, sır metin olarak okunarak imzalayın; sonra sonucu başlığın v1 ögesiyle karşılaştırın. Yukarıdaki bölüm bunu alan alan gezer. Neredeyse herkesi düşüren şey ilk adımdır: gövde yalnız başına Stripe’ın imzaladığı şey değildir.
Bir GitHub webhook imzasını nasıl doğrularım?
Ham istek gövdesini webhook’un sırrıyla, sır metin olarak okunarak, SHA-256 ile imzalayın ve hex özetini X-Hub-Signature-256 başlığıyla karşılaştırın. Buraya yapıştırırken sha256= etiketi kalabilir. GitHub çözülmüş bir örnek yayımlar — Hello, World! gövdesi ve It's a Secret to Everybody sırrı — ve bu, tarifi okuyuşunuzu gerçek bir teslimde denemeden önce kontrol etmenin en hızlı yoludur.
Bir Shopify webhook imzasını nasıl doğrularım?
Ham istek gövdesini, webhook’un ait olduğu uygulamanın istemci sırrıyla, sır metin olarak okunarak, SHA-256 ile imzalayın ve Base64 özetini X-Shopify-Hmac-SHA256 başlığıyla karşılaştırın. Başlık değerinin tamamı olduğu gibi yapıştırılır — sondaki eşittir işareti Base64 dolgusudur. Eşleşmediğinde alışılmış neden, gövdeyi işleyiciniz onu görmeden ayrıştırmış bir ara katmandır.
Başka bir sağlayıcının webhook imzasını nasıl doğrularım?
Dört soru bunu çözer ve gönderenin belgelerinde dördü de vardır: hangi başlık imzayı taşıyor, gerçekte hangi dize imzalanıyor, sır nasıl okunmalı ve özet hex mi Base64 mü. Bunları yukarıdaki alanlara girin. Yine de eşleşmiyorsa cevap neredeyse her zaman ikincisidir — pek çok gönderen gövdeyi yalnız başına değil, kendisine eklenmiş bir şeyle birlikte imzalar.

İlgili araçlar