Genel olarak güvenilir kabul edilen herhangi bir SHA-256 javascript uygulaması var mı?


101

Bir forum için bir giriş yazıyorum ve sunucuya göndermeden önce javascript'te parola istemci tarafına hash işlemi uygulamam gerekiyor. Hangi SHA-256 uygulamasına gerçekten güvenebileceğimi bulmakta güçlük çekiyorum. Herkesin kullandığı bir tür yetkili komut dosyası olmasını bekliyordum, ancak hepsi kendi uygulamaları olan bir sürü farklı proje buluyorum.

Başkalarının kripto para birimini kullanmanın her zaman bir inanç sıçraması olduğunun farkındayım ve bunu kendiniz gözden geçirmeye yetkili değilseniz ve "güvenilir" in evrensel bir tanımı yoktur, ancak bu, bir tür olması gereken kadar yaygın ve önemli bir şey gibi görünüyor. ne kullanılacağı konusunda fikir birliği. Ben sadece saf mıyım?

Yorumlarda çok fazla yer aldığı için düzenleyin: Evet, sunucu tarafında yine daha sıkı bir hash yapıyoruz. İstemci tarafı hashing, veritabanına kaydettiğimiz nihai sonuç değildir. İstemci tarafı hashing, insan istemcinin talep etmesidir. Belirli bir neden belirtmediler, muhtemelen aşırı öldürmeyi seviyorlar.


9
Konu dışına çıkmak istemem ama neden istemci tarafında şifreyi karıştırıyorsunuz?
Steve

5
@ddyer Yakın bile değil. "Kendi algoritmanızı yuvarlamayın" kendi algoritmanızı icat etmek , bir algoritmanın kendi uygulamanızı yazmak , kripto algoritmalarının üzerine kendi protokolünüzü geliştirmek veya mümkün olduğu kadar yüksek seviyeli bir soyutlama kullanarak hemen hemen her şeyi yapmak için geçerlidir. Güvenli bir çekirdeğe bağlı kalmanın ve yalnızca yapıştırıcı kod yazmanın güvende olacağını düşünüyorsanız, kötü bir zaman geçireceksiniz.
Stephen Touset

26
Sınama / yanıt protokolü olmayan karma bir parola kullanıyorsanız, karma parola paroladır ve parolayı açık metin olarak iletmekle gerçekten aynıdır.
ddyer

26
@ddyer Kullanıcının şifresiz metin şifresini, özellikle bizim sitemiz için olmasa bile, kullanabilecekleri diğer tüm siteler için korumanın bir değeri vardır. Bize yardımcı olmayacak, ancak bir yeri batırırsak potansiyel olarak kullanıcıya yardımcı olabilecek kolay bir düzeltme. Ve dediğim gibi, müşteri isteği, istesem bile yapabileceğim hiçbir şey yok.
jono

5
@Anorov Fikrimi değiştirmeye fazlasıyla açığım :) ama bu durumda, amacınızın nasıl geçerli olduğunu gerçekten anlamıyorum. Parolayı iki kez hash ediyoruz: bir kez basit bir SHA-256 ile istemci tarafında ve bir kez sunucu tarafında daha zorlu bir şeyle. Birincisi düz metni MITM veya benzeri durumlarda korur ve ikincisi kaba koruma içindir. Veritabanına ve yönetici karmasına sahip olsanız bile, girişi doğrulamak için bunu doğrudan kullanamazsınız.
jono

Yanıtlar:


116

GEÇMİŞ: Birçok modern tarayıcı artık kripto işlemleri için birinci sınıf desteğe sahiptir. Aşağıdaki Vitaly Zdanevich'in cevabına bakın.


Stanford JS Kripto Kütüphane SHA-256 bir uygulamasını içerir. JS'deki kripto, diğer uygulama platformları kadar iyi incelenmemiş olsa da, bu en azından kısmen kriptografide köklü ve güvenilir bir isim olan Dan Boneh tarafından geliştirildi ve bir dereceye kadar sponsor oldu. ve projenin gerçekte ne yaptığını bilen biri tarafından denetlendiği anlamına gelir. Proje ayrıca NSF tarafından da destekleniyor .

Bununla birlikte, şunu
belirtmek gerekir ki ... ... şifreyi göndermeden önce istemci tarafında hashlerseniz, karma şifredir ve orijinal şifrenin önemi kalmaz. Saldırgan kullanıcının kimliğine bürünmek amacıyla istihbarat bilgisine sadece karma gerekiyor ve bu karma sunucusunda değiştirilmemiş saklandığı takdirde, o zaman sunucu depoluyor gerçek düz metin parola (hash) .

Yani güvenliğiniz artık daha kötü çünkü daha önce güvenilen bir plana kendi geliştirmelerinizi eklemeye karar verdiniz .


32
Ancak sunucuda yeniden karma oluşturduğunuzda, bu uygulama tamamen meşrudur.
Nick Brunt

13
@NickBrunt, sunucuda karma oluşturduysanız, iletilen şifreyi kaydetmiyorsunuz, ancak şifre karmasını iletmenin aksine orijinal şifreyi iletmenin ötesinde herhangi bir güvenlik eklemediniz, çünkü her iki durumda da ilettiğiniz gerçek parola.
tylerl

55
Doğru, ancak muhtemelen İnternette başka bir yerde düz metin olarak kullanılan bir şifre göndermekten daha kötü değil.
Nick Brunt

15
@ NickBrunt'a katılıyorum. Saldırganın, birkaç yerde kullanılabilecek orijinal parola yerine yalnızca bu belirli uygulamaya sığabilecek rastgele bir karma dizesi okuması daha iyidir.
Aebsubis

13
İstemci tarafında hashing kullanmam gerekiyor çünkü sunucunun kullanıcının şifresiz metin şifresini görmesini istemiyorum. Sağladığım hizmete ek güvenlik için değil, kullanıcıya karşı. Yalnızca kullanıcının hashini sabit bir tuzla (kullanıcı başına sabit, global olarak değil) saklamakla kalmıyorum, aynı zamanda onu, koklamaya karşı ağ üzerinden biraz ekstra güvenlik sağlayan her girişte rastgele bir tuzla yeniden karma hale getiriyorum. Sunucu tehlikeye atılırsa oyun biter, ancak bu gerçekten p2p olmayan herhangi bir şey için doğrudur.
Hatagashira

62

On https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest ben iç js modülünü kullanan bu parçacık bulundu:

async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder().encode(message);                    

    // hash the message
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

    // convert ArrayBuffer to Array
    const hashArray = Array.from(new Uint8Array(hashBuffer));

    // convert bytes to hex string                  
    const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
    return hashHex;
}

Not o crypto.subtlesadece mevcut içinde httpsveya localhost- ile yerel kalkınma için örneğin python3 -m http.serversize bu satırı ekleyin getirmemiz yeterlidir /etc/hosts: 0.0.0.0 localhost

Yeniden başlatın - ve localhost:8000çalışarak açabilirsiniz crypto.subtle.


2
Bu harika. Teşekkür ederim. Node.js'de karşılaştırılabilir bir API var mı?
Con Antonakos


18

Forge'un SHA-256 uygulaması hızlı ve güvenilirdir.

Birkaç SHA-256 JavaScript uygulamasında test çalıştırmak için http://brillout.github.io/test-javascript-hash-implementations/ adresine gidin .

Makinemdeki sonuçlar, forge'ın en hızlı uygulama olduğunu ve ayrıca kabul edilen cevapta belirtilen Stanford Javascript Crypto Library'den (sjcl) önemli ölçüde daha hızlı olduğunu gösteriyor.

Forge 256 KB büyüklüğündedir, ancak SHA-256 ile ilgili kodun çıkarılması boyutu 4,5 KB'ye düşürür, bkz. Https://github.com/brillout/forge-sha256


İle kurmayı başardım npm install node-forgeama şimdi kitaplığı nasıl kullanacağım dizeden bir hash oluşturabilir foomiyim?
kullanıcı

17

İlgilenenler için bu, aşağıdakileri kullanarak SHA-256 hash oluşturma kodudur sjcl:

import sjcl from 'sjcl'

const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)

5
Bu, çözümü orada kullanmak isteyenler için kabul edilen cevaba dahil edilmelidir. (Heck, kendi belgelerinde bile bunun gibi bir pasajı yoktur)
MagicLegend

Bu en iyi cevap. Kripto çözümünü deniyordum ama benim için işe yaramadı.
Augusto Gonzalez

12

Hayır, şifre güvenliğini artırmak için tarayıcı JavaScript'i kullanmanın bir yolu yoktur. Bu makaleyi okumanızı şiddetle tavsiye ederim . Sizin durumunuzda en büyük sorun, tavuk yumurtası sorunudur:

Javascript kriptografisini iletirken "tavuk yumurtası sorunu" nedir?

Ağın bir parola vereceğine güvenmiyorsanız veya daha kötüsü, sunucuya kullanıcı sırlarını saklamaması için güvenmiyorsanız, güvenlik kodunu teslim etmeleri için onlara güvenemezsiniz. Siz kriptoyu tanıtmadan önce şifreleri koklayan veya günlükleri okuyan aynı saldırgan, siz yaptıktan sonra kripto kodunu ele geçiriyor.

[...]

Javascript şifreleme kodunu iletmek için neden TLS / SSL kullanamıyorum?

Yapabilirsin. Göründüğünden daha zor, ancak JavaScript kriptoyu SSL kullanarak bir tarayıcıya güvenli bir şekilde aktarıyorsunuz. Sorun şu ki, SSL ile güvenli bir kanal kurduğunuzda, artık Javascript kriptografisine ihtiyacınız yok; "gerçek" kriptografiniz var.

Bu da buna yol açar:

Javascript'te kripto kodu çalıştırmanın sorunu, kripto'nun bağlı olduğu herhangi bir işlevin, barındırma sayfasını oluşturmak için kullanılan herhangi bir içerik parçası tarafından sessizce geçersiz kılınabilmesidir. Kripto güvenliği, sürecin başlarında (sahte rastgele sayılar oluşturarak veya algoritmalar tarafından kullanılan sabitler ve parametrelerle oynayarak) veya daha sonra (anahtar materyalini bir saldırgana geri döndürerek) veya --- en olası senaryoda geri alınabilir --- kriptoyu tamamen atlayarak.

Herhangi bir Javascript kodu parçasının yürütme ortamını doğrulamanın güvenilir bir yolu yoktur. Javascript kripto kodu "Gerçekten rastgele bir sayı oluşturucusuyla mı yoksa bir saldırgan tarafından sağlanan birinin bir kopyasıyla mı uğraşıyorum?" Diye soramaz. Ve kesinlikle "bu kripto sırrı ile benim, yazarın onayladığı yollar dışında kimsenin bir şey yapmasına izin verilmez" diyemez. Bunlar genellikle kripto kullanan diğer ortamlarda sağlanan iki özelliktir ve bunlar Javascript'te imkansızdır.

Temelde sorun şudur:

  • Müşterileriniz sunucularınıza güvenmediğinden ekstra güvenlik kodu eklemek isterler.
  • Bu güvenlik kodu sunucularınız (güvenmedikleri) tarafından teslim edilir.

Veya alternatif olarak,

  • Müşterileriniz SSL'ye güvenmiyor, bu yüzden ekstra güvenlik kodu kullanmanızı istiyorlar.
  • Bu güvenlik kodu SSL aracılığıyla teslim edilir.

Not: Ayrıca, SHA-256 bunun için uygun değildir, çünkü tuzsuz, yinelenmemiş şifreleri zorlamak çok kolaydır . Yine de bunu yapmaya karar verirseniz, bir bcrypt , scrypt veya PBKDF2 uygulaması arayın .


1
Bu doğru değil. İstemci tarafında hashing uygulanarak şifre güvenliği geliştirilebilir. Ayrıca sunucu tarafında PBKDF2 gibi bir şey kullanıldığı sürece SHA-256'nın uygun olmaması da yanlıştır. Üçüncüsü, matasano makalesi yararlı bilgiler içeriyor olsa da, temelde tavuk ve yumurta sorununu temelden değiştiren tarayıcı uygulamalarımız olduğundan, temel nokta yanlış.
user239558

2
PBKDF2'nin istemcide kullanılması gerektiği konusunda haklısınız. İstemci tarafındaki javascript crypto'ya karşı öfke, ilk sayfanın ve sonraki isteklerin aynı güvenlik özelliklerine sahip olduğunu varsayar. Bu, ilk sayfanın ayrı olarak kurulduğu ve statik olduğu tarayıcı uygulamaları için kesinlikle doğru değildir. Ayrıca sonsuza kadar önbelleğe sahip herhangi bir sayfa için de doğru değildir. Bu durumlarda, bir istemci tarafı programı kurarken olduğu gibi tamamen aynı olan TOFU'dur. Bu, statik ve dinamik sayfaların sunumunun sunucuda ayrıldığı daha karmaşık kurulumlarda da geçerli olabilir.
user239558

3
Sistem yöneticilerinin kullanıcı şifrelerine erişimini önlemek meşrudur, bu nedenle istemci tarafında hashing, DBA'ların veya diğer BT uzmanlarının kullanıcı şifrelerini görmesini ve diğer hizmetlere / sistemlere erişmek için yeniden kullanmayı denemesini engeller, çünkü birçok kullanıcı şifrelerini tekrar eder. .
Yamada

1
@Xenland Tek yaptığınız "token + password" olan yeni bir şifre oluşturmak. Tüm orijinal sorunlar hala geçerlidir. Örneğin, bir saldırgan JavaScript'i kodla değiştirerek kendilerine jeton + şifre gönderebilir.
Brendan Long

2
@Xenland Tavuk ve yumurta sorununun gönderdiğiniz taleplerle ilgisi yok. Sorun, istemcinizin güvenlik çalışması yapmak için güvenli olmayan bir bağlantı üzerinden indirdiği JavaScript kodunu kullanmasıdır . JavaScript'i bir web tarayıcısına güvenli bir şekilde göndermenin tek yolu, onu TLS üzerinden sunmaktır ve bunu yaptıktan sonra, bağlantınız zaten güvenli olduğu için başka bir şey yapmanıza gerek kalmaz. Bir saldırganın değiştirebileceği JavaScript kodu kullanıyorsanız, protokolünüzün ne olduğu önemli değildir.
Brendan Long

10

Bu uygulamanın kullanımını çok kolay buldum. Ayrıca cömert bir BSD tarzı lisansa sahiptir:

jsSHA: https://github.com/Caligatio/jsSHA

Bir SHA-256 karmasının onaltılık dizge temsilini elde etmek için hızlı bir yola ihtiyacım vardı. Sadece 3 satır aldı:

var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");

1

Tylerl'ın bahsettiği Stanford lib'inden başka. Jsrsasign'ı çok faydalı buldum (Github repo burada: https://github.com/kjur/jsrsasign ). Tam olarak ne kadar güvenilir olduğunu bilmiyorum, ancak API'sini SHA256, Base64, RSA, x509 vb. Kullandım ve oldukça iyi çalışıyor. Aslında, Stanford kütüphanesini de içerir.

Tek yapmak istediğiniz SHA256 ise, jsrsasign bir abartı olabilir. Ancak ilgili alanda başka ihtiyaçlarınız varsa, bunun uygun olduğunu düşünüyorum.


2
Kullanımı daha güvenli ve daha hızlı developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
Vitaly Zdanevich

2
Kabul ediyorum, ancak adil olmak gerekirse, bu soruyu 2015'te cevapladım, mozilla'nın web kripto API spesifikasyonu Ocak 2017
Faraway
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.