Soru Char [] neden Dize şifreleri için tercih edilir?


Swing'de şifre alanı bir getPassword() (döner char[]) her zamanki yöntem yerine getText() (döner String) yöntem. Benzer şekilde, kullanmama önerisine rastladım. String şifreleri işlemek için.

Neden yapıyor String şifreler söz konusu olduğunda güvenlik açısından bir tehdit oluşturuyor mu? Kullanmak için rahatsız edici hissediyor char[].


2901
2018-01-16 14:20


Menşei


Önerinin kaynağını söyleyebilir misiniz? Gerçekten bunun için bir sebep düşünemiyorum. char[] belki de en amatör tehditlerden daha güvenli olmak. - Viruzzo
@Viruzzo javadocs'a bir göz atın. getText() yöntem JPasswordField lehine imtiyazlı getPassword() "güvenlik nedeniyle". - dogbane
char []? Neden byte değil []? Herhangi bir thread dökümü / yığın analizöründe Dizeleri görebilirsiniz ve bir şifre içeriyorsa bunu fark etmek kolaydır. Char [] için daha zordur, ancak yine de, yığın analizciniz karakterleri birer birer gösterecekse, String ile aynı olacaktır. Byte [] için olası değil. - mvmn
Bunun önemli olabileceği geçerli bir senaryo oluşturmak için, adli tıpta, yazılım şifrelemesi kullandıkları takdirde, soruşturma gerektirmeyen bilgisayarların belleğinin boşaltılmasından önce kapatılmamasını sağlamak yaygın bir uygulamadır. En iyi şifreleme sistemi bile şifre çözme yeteneğine sahip bir devleti korumalıdır. - Zenexer
@scottlafoy İkisi de char[] ve String nesneler referans olarak geçecek; bireysel char değerler olmayacak. Nesneler tarafından geçirildiğinde değerreferans değil, birden çok kopya oluşturuldu. Genellikle bu bir sorun değildir, çünkü bu nesneler genellikle küçük olacak şekilde tasarlanmıştır. - Zenexer


Cevaplar:


Dizeler değişmez. Bu, bir kez oluşturduğunuz anlamına gelir Stringeğer başka bir süreç hafızayı boşaltabilirse, bir yolu yoktur. yansıma) daha önce verilerden kurtulabilirsiniz çöp toplama başladı.

Bir dizi ile, işiniz bittikten sonra açık bir şekilde silebilirsiniz. Diziyi istediğiniz herhangi bir şeyle üzerine yazabilir ve şifre toplama işleminden önce bile sistemde herhangi bir şifre bulunmayacaktır.

Yani evet, bu olduğu bir güvenlik endişesi - ama kullanmak bile char[] sadece bir saldırganın fırsat penceresini azaltır ve sadece bu özel saldırı türü içindir.

Yorumlarda belirtildiği gibi, çöp toplayıcı tarafından taşınan dizilerin bellekteki veriyi kopyalar bırakması olasıdır. Bunun uygulamaya özgü olduğuna inanıyorum - çöp toplayıcı Mayıs ayı Bu tür şeylerden kaçınmak için tüm belleği temizleyin. Olsa bile, hala char[] gerçek karakterleri bir saldırı penceresi olarak içerir.


3720
2018-01-16 14:26



Anlayışım, çalışma zamanı ile yapılabilen hafıza yeniden düzenlenmesiyle, hatta char[] hafızaya bırakılabilir ve bu bellek yeniden kullanılıncaya kadar asla temizlenmez. Bunu doğrulayan bir kaynak bilmiyorum. Her iki durumda da, String'in GC zamanında temizleneceğinden kuşkuluyum. Bir Object'in bu bellek üzerinde yeniden tahsis edildiği zamanda. - Mark Peters
@Mark Peters: Eğer GC diziyi başlatırsa, karakter dizisini boşaltmadan önce başka bir kopyanız olur. Ama bu kopya en azından hafızanın ağır bir bölgesinde kullanılıyor, bu yüzden şanslar yüksek, üstüne yazılır. - Mnementh
@ Xeon06: .NET'te var SecureString Henüz daha iyi - ama kullanımı nispeten acı verici. - Jon Skeet
Bu veriyi okuyabilecek kötü niyetli bir varlığın sisteminize zaten okuma erişimi olduğunu biliyor muyuz? Görünüşe göre bu dize [] yerine String yapmak yerine okyanusta öfkelenmek gibi görünüyor. - corsiKa
@corsika: Cevapta bahsettiğim gibi, belirli bir saldırı vektörünü azaltıyor, hepsi bu. Bir saldırgan için işleri zorlaştırır. - Jon Skeet


Diğer öneriler burada geçerli gözükse de, başka iyi bir sebep vardır. Düz ile String çok fazla şansınız var Parolayı yanlışlıkla günlüklere yazdırmak, monitörler veya başka bir güvensiz yer. char[] daha az savunmasızdır.

Bunu düşün:

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}

Baskılar:

String: Password
Array: [C@5829428e

1080
2018-01-16 19:37



@voo, ama doğrudan yazma yoluyla akışa ve birleştirme işlemine giriş yapacağınızdan şüpheliyim. günlük çerçevesi, char [] 'ı iyi çıktıya dönüştürür - bestsss
@ Thr4wn Varsayılan uygulaması toString olduğu classname@hashcode. [C temsil char[]kalanlar onaltılı karma kodudur. - Konrad Garus
İlginç fikir. Bunun, diziler için anlamlı bir toString'e sahip Scala'ya aktarılmadığını belirtmek isterim. - mauhiz
Yazarım Password Bunun için sınıf türü. Daha az belirsiz ve yanlışlıkla bir yere geçmek zor. - rightfold
Birisi neden char dizisinin bir Object olarak yayınlanacağını varsaysın? Bu cevabın neden her birini beğendiğimi anlayamadım. Bunu yaptığınızı varsayalım: System.out.println ("Parola" .toCharArray ()); - GC_


Resmi bir belge alıntılamak için Java Şifreleme Mimarisi kılavuzu hakkında diyor char[] vs. String şifreler (şifre tabanlı şifrelemeyle ilgili, fakat bu daha genel olarak elbette şifrelerle ilgilidir):

Parolayı bir nesnede toplamak ve saklamak mantıklı görünebilir   türü java.lang.String. Ancak, burada uyarı: Objects   tip String Değişmezdir, yani, tanımlanmış hiçbir yöntem yoktur.   içeriğini değiştirmenize (üzerine yazmanıza) veya String   kullanımdan sonra. Bu özellik yapar String için uygun olmayan nesneler   Kullanıcı şifreleri gibi güvenlik açısından hassas bilgileri saklamak. Sen   her zaman güvenlik açısından hassas bilgileri toplayıp depolamalı    char bunun yerine dizi.

Java Programlama Dili, Sürüm 4.0 için Güvenli Kodlama Yönergesi 2-2 aynı zamanda benzer bir şey de yazıyor (aslında başlangıçta oturum açma bağlamında):

Kılavuz 2-2: Son derece hassas bilgileri kaydetme

Sosyal Güvenlik numaraları (SSN) ve bazı bilgiler   şifreler çok hassastır. Bu bilgi saklanmamalıdır   gerekenden daha uzun ve nerede görülebilir, hatta   yöneticiler. Örneğin, günlük dosyalarına ve   varlığı, aramalar yoluyla tespit edilmemelidir. Bazı geçici   veri char dizileri gibi değişebilir veri yapılarında tutulabilir ve   kullanımdan hemen sonra temizlenmelidir. Veri yapılarının temizlenmesi azaldı   Nesneler gibi tipik Java çalışma zamanı sistemlerinde etkinliği   belleğe programcıya şeffaf şekilde.

Bu kılavuzun aynı zamanda uygulama ve kullanımı için etkileri vardır.   veri anlam bilgisi olmayan alt düzey kütüphaneler   Onlar uğraşıyorlar. Örnek olarak, düşük seviyeli bir dizge ayrıştırma   kütüphane çalıştığı metni kaydedebilir. Bir uygulama SSN'yi ayrıştırabilir   kütüphane ile. Bu SSN'lerin olduğu bir durum yaratır.   günlük dosyalarına erişimi olan yöneticiler için kullanılabilir.


610
2018-01-17 03:20



Bu tam olarak Jon'un cevabının altında bahsettiğim kusurlu / sahte referans, çok iyi bilinen bir kaynaktır. - bestsss
@bestass ayrıca bir referans gösterebilir misiniz? - user961954
@bestass üzgünüm, ama String oldukça iyi anlaşılmış ve JVM'de nasıl davrandığını ... kullanmak için iyi sebepler var char[] yerine String şifreleri güvenli bir şekilde ele alırken. - SnakeDoc
Bir kez daha şifre, tarayıcıdan 'dize' olarak istekte olmayan bir dize olarak geçirilir olsa da? ne yaparsanız yapın, bu bir dizedir, hangi noktada harekete geçmeli ve atılmalıdır, hiç bellekte saklanamaz mı? - Dawesi


Karakter dizileri (char[]) Her karakteri sıfıra ayarlayarak ve Strings değil kullanarak temizlenebilir. Birisi bellek görüntüsünü bir şekilde görebiliyorsa, Dizeler kullanılıyorsa düz metin halinde bir şifre görebilirler. char[] 0'lı veriler temizlendikten sonra parola güvenlidir.


305
2018-01-16 14:27



Varsayılan olarak güvenli değil. Bir web uygulamasından bahsediyorsak, çoğu web kutusu şifreyi HttpServletRequest düz metin içinde nesne. Eğer JVM versiyonu 1.6 veya daha düşük ise, permgen uzayında olacaktır. 1,7 ise, toplanana kadar hala okunabilir. (Bu ne zaman.) - avgvstvs
@avgvstvs: dizeler otomatik olarak yalnızca dizinin dizeleri için uygulanan permgen boşluğuna taşınır. Bunun yanı sıra, permgen alanı da sadece daha düşük bir oranda, çöp toplama tabi tutulur. Permgen alanı ile ilgili asıl mesele, sabit boyutudur, bu da hiç kimsenin düşüncesizce çağırmamasının nedeni tam da budur. intern() keyfi dizeler üzerinde. Ama sen haklısın. String Örnekler ilk sırada (toplanana kadar) var ve bunları char[] daha sonra diziler onu değiştirmez. - Holger
@Holger bkz. docs.oracle.com/javase/specs/jvms/se6/html/...  "Aksi takdirde, CONSTANT_String_info yapısı tarafından verilen Unicode karakterlerinin sırasını içeren yeni bir sınıf Dizesi örneği oluşturulur; bu sınıf örneği dize değişmez türetmesinin sonucudur. Son olarak, yeni String örneğinin intern yöntemi çağrılır." 1.6'da, JVM, özdeş sekanslar tespit edildiğinde sizin için stajyer arardı. - avgvstvs
@Holger, sen doğru havuz ve dizgi havuzunu karıştırdım, ama aynı zamanda bu permgen uzayında yanlış. bir tek dahili dizelere uygulanır. 1,7'den önce, hem constant_pool hem de string_pool permgen boşluğunda kalıyordu. Bu, yığına ayrılan String'lerin tek sınıfı dediğin gibi oldu. new String() veya StringBuilder.toString()  Çok sayıda dize sabitiyle uygulamalar yaptım ve sonuç olarak çok fazla permgen sürünme yaşadık. 1,7'ye kadar. - avgvstvs
@avgvstvs: iyi, dizge sabitleri, JLS'nin gerektirdiği gibi, her zaman internededir, dolayısıyla dahili dizelerin permgen boşluğuna bittiği, dize sabitlerine dolaylı olarak uygulanan ifadedir. Tek fark, dize sabitlerinin ilk etapta permgen uzayında yaratılmış olmasıdır. intern() keyfi bir dizede, permgen boşluğuna eşdeğer bir dizinin tahsis edilmesine neden olabilir. Bu nesne paylaşan aynı içeriğe ait herhangi bir dize yoksa, ikinci öğe GC’ed olabilir. - Holger


Bazı insanlar, artık ihtiyacınız olmadığında şifreyi saklamak için kullanılan hafızanın üzerine yazmanız gerektiğine inanırlar. Bu, saldırganın parolayı sisteminizden okuması gereken zaman penceresini azaltır ve saldırganın bunu yapmak için JVM belleğini ele geçirmek için yeterli erişim gereksinimini tamamen ortadan kaldırır. Bu kadar çok erişimi olan bir saldırgan, anahtar olaylarınızı yakalayabilir ve bunu tamamen işe yaramaz hale getirir (AFAIK, eğer yanılıyorsam lütfen beni düzeltin).

Güncelleştirme

Yorumlar sayesinde cevabımı güncellemeliyim. Görünüşe göre, bu, bir şifrenin sabit disk sürücüsüne inebileceği süreyi kısalttığı için (çok) küçük bir güvenlik iyileştirmesi ekleyebilecek iki durum vardır. Yine de çoğu kullanım durumu için çok fazla olduğunu düşünüyorum.

  • Hedef sisteminiz kötü bir şekilde yapılandırılmış olabilir veya bunu varsaymanız gerekir ve çekirdek dökümler hakkında paranoyak olmanız gerekir (sistemler bir yönetici tarafından yönetilmediyse geçerli olabilir).
  • Yazılımınız, saldırganın donanıma erişim kazanmasıyla veri sızıntılarını önlemek için aşırı paranoyak olmalıdır - TrueCrypt (Sonlandırıldı), VeraCryptveya CipherShed.

Mümkünse, çekirdek dökümlerini ve takas dosyasını devre dışı bırakmak her iki problemi de ele alacaktır. Ancak, yönetici haklarına gereksinim duyarlar ve işlevselliği azaltabilir (kullanmak için daha az bellek) ve RAM'i çalışan bir sistemden çekebilmek yine de geçerli bir sorun olacaktır.


183
2018-01-16 14:32



"Tamamen yararsız" yerine "sadece küçük bir güvenlik iyileştirmesi" ile yer değiştirirdim. Örneğin, bir tmp dizinine, kötü yapılandırılmış bir makineye ve uygulamanızda bir çökmeye erişiminiz olduğunda bir bellek dökümünden yararlanabilirsiniz. Bu durumda bir keylogger yükleyemezsiniz, fakat siz could çekirdek dökümü analiz eder. - Joachim Sauer
Şifrelenmemiş verileri bellekten bellekten sildiğinizde, en iyi uygulama olarak kabul edilmez, çünkü kusursuz (değil); ama tehdit tehdidi seviyenizi azalttığı için. Gerçek zamanlı saldırılar bunu yaparak engellenmez; ancak bir bellek koruma görüntüsünde geriye dönük bir saldırıya maruz kalan veri miktarını önemli ölçüde azaltarak bir hasar azaltma aracına hizmet ettiğinden (örneğin, bir takas dosyasına yazılan uygulama belleğinizin bir kopyası veya bellekte okunduğunda okunan veriler) çalışan bir sunucudan ve devleti başarısız olandan farklı bir yere taşındı). - Dan Neely
Bu cevabın tutumuna katılıyorum. Çoğu güvenlik ihlalinin, bellekteki bitlerden çok daha yüksek bir soyutlama seviyesinde oluştuğunu öne sürmek için girişimde bulunacağım. Tabii ki, büyük ölçüde endişe verici olabilecek hiper-güvenli savunma sistemlerinde senaryolar vardır, ancak bu seviyede ciddi bir şekilde düşünme, .NET veya Java'nın kaldırıldığı uygulamaların% 99'u için fazladır (çöp toplama ile ilgili olduğu gibi). - kingdango
Sunucu belleğinin Heartbleed penetrasyonundan sonra, şifreleri açığa çıkarırken, "sadece küçük bir güvenlik iyileştirmesi" dizesini "şifreler için String kullanmamanız için kesinlikle gerekli" ile değiştiririm, ancak bunun yerine bir char [] kullanın. - Peter vdL
@PetervdL, yalnızca belirli bir yeniden kullanılan arabellek koleksiyonunun okunmasına izin verdi (hem güvenlik açısından kritik veri hem de ağ G / Ç'leri arasında, - performans nedenlerinden ötürü - temizlemeden), bunu bir Java Dizesi ile birleştiremezsiniz, çünkü tasarım gereği yeniden kullanılamazlar. . Bir String'in içeriğine ulaşmak için Java'yı kullanarak rastgele bir belleği okuyamazsınız. Java Dizeleri'nde, kalp atışlarına neden olan dil ve tasarım sorunları mümkün değildir. - josefx


  1. Dizeler değişmez Java'da parolayı düz metin olarak saklarsanız, Çöp toplayıcısını temizleyene kadar bellekte kullanılabilir ve yeniden kullanılabilirlik için Dizeler'de String dizgileri kullanıldığı için oldukça uzun bir süre bellekte kalması olasılığı yüksektir. bir güvenlik tehdidi oluşturur. Bellek dökümünde erişimi olan herkes şifreyi açık metinde bulabilir
  2. Java önerisi kullanma getPassword() char [] döndüren ve kullanımdan kaldırılmış JPasswordField yöntemi getText() Güvenlik nedenini belirten açık metinde şifre döndüren yöntem.
  3. toString () günlük dosyasında veya konsolda düz metin yazdırma riski vardır ancak Dizi kullanırsanız dizinin içeriğini basmazsınız, bunun yerine bellek konumu yazdırılır.

    String strPwd = "passwd";
    char[] charPwd = new char[]{'p','a','s','s','w','d'};
    System.out.println("String password: " + strPwd );
    System.out.println("Character password: " + charPwd );
    

    Dize şifresi: passwd

    Karakter şifresi: [C @ 110b2345

Son düşünceler: Char [] kullanarak sadece içeriği değil, daha güvenli olması için içeriği silmeniz gerekir. Düz metin yerine karma veya şifreli parola ile çalışmayı ve kimlik doğrulama tamamlanır tamamlanmaz bellekten temizlemenizi öneririm.


117
2017-12-27 20:22



"Bellek dökümünden yararlanan herhangi biri, şifreyi açık metinde bulabildiğinden" Bellek dökümünden nasıl erişebilir ve orada bir şifre bulabilirim? " - Mohit Kanwar
@MohitKanwar jmap veya jvisualvm yoluyla bir bellek dökümü tetikleyin. Heapdumponoutofmemoryerror ayarlanmışsa, bellek yetersizliğine neden olarak uzak bir yığın dökümü tetikleyebilirsiniz. Dökümü aldıktan sonra jersonualvm veya eclipse hafıza analiz aracı veya komut satırı araçları ile yürüyebilir ve tüm Nesneleri ve değerlerini inceleyebilirsiniz. - Ryan


Bunun geçerli bir öneri olduğunu sanmıyorum, ama en azından nedenini tahmin edebilirim.

Motivasyonun, şifrenin tüm izini bellekte derhal ve kullanımdan sonra kesinlikle silmenizi sağlamak istediğini düşünüyorum. Birlikte char[] Dizinin her bir öğesinin bir boş veya bir şeyle üzerine yazabilirsiniz. İçsel değerini düzenleyemezsiniz. String bu şekilde.

Ama bu tek başına iyi bir cevap değil; neden sadece bir referans char[] veya String kaçmadı mı O zaman güvenlik sorunu yok. Ama şey şu ki String nesneler olabilir intern()teoride ve sabit havuzun içinde canlı tutuldu. Kullanıyorum varsayalım char[] bu olasılığı yasaklar.


72
2018-01-16 14:27



Sorun şu ki, referansların "kaçış" olacak ya da olmayacak. Sadece bu dizeler, bir süre daha hafızada değiştirilmeden kalır. char[] Değiştirilebilir ve daha sonra toplanıp toplanmadığı anlaşılır. Dize internasyonunun gayri resmi olmayanlar için açıkça yapılması gerektiğinden, char[] Statik bir alan tarafından referans alınabilir. - Groo
form defterinden bir dize olarak bellekte şifre değil mi? - Dawesi


Yanıt zaten verildi, ancak son zamanlarda Java standart kütüphaneleriyle keşfettiğim bir sorunu paylaşmak istiyorum. Artık şifre dizelerini değiştirerek çok dikkatli davranıyorlar. char[] Her yerde (tabii ki iyi bir şeydir), diğer güvenlik açısından önemli veriler bellekten temizlendiğinde göz ardı ediliyor gibi görünmektedir.

Ben örn. Özel anahtar sınıf. Bazı işlemleri gerçekleştirmek için PKCS # 12 dosyasından özel bir RSA anahtarı yükleyeceğiniz bir senaryo düşünün. Bu durumda, şifrenin tek başına çalınması, anahtar dosyaya fiziksel erişimin gerektiği gibi kısıtlandığı sürece size yardımcı olmaz. Bir saldırgan olarak, anahtarı şifre yerine doğrudan aldıysanız çok daha iyi olurdu. İstenen bilgi sızdırabilir manifold, çekirdek dökümleri, bir hata ayıklayıcı oturumu veya takas dosyaları sadece bazı örneklerdir.

Ve ortaya çıktığı gibi, özel bilginin temizlenmesine izin veren hiçbir şey yoktur. PrivateKey Bellekten, ilgili bilgileri oluşturan baytları silmenizi sağlayan bir API olmadığı için.

Bu kötü bir durum, bu kâğıt Bu durumun potansiyel olarak nasıl kullanılabileceğini açıklar.

OpenSSL kütüphanesi, örneğin, özel anahtarlar serbest bırakılmadan önce kritik bellek bölümlerinin üzerine yazar. Java çöp topladığından, anahtarı kullandıktan sonra hemen uygulanacak olan Java anahtarlarının özel bilgilerini silmek ve geçersiz kılmak için açık yöntemlere gereksinimimiz olacaktır.


58
2018-01-19 19:39



Bunun bir yolu, bir uygulamanın kullanılmasıdır. PrivateKey Bu, özel içeriğini belleğe yüklemez: örneğin bir PKCS # 11 donanım belirteci aracılığıyla. Belki de PKCS # 11'in bir yazılım uygulaması belleği el ile temizlemeyle ilgilenebilir. Belki de NSS mağazası gibi bir şey kullanarak PKCS11 Java'da depo tipi daha iyidir. KeychainStore (OSX keystore) özel anahtarın tüm içeriğini kendi içine yükler. PrivateKey örnekler, ancak buna gerek yok. (Ne olduğundan emin değilsiniz. WINDOWS-MY KeyStore, Windows'ta çalışır.) - Bruno
@Bruno Sure, donanım tabanlı belirteçler bundan muzdarip değil, ya da bir yazılım anahtarını kullanmak için daha fazla veya daha az zorlandığınız durumlar? Her dağıtımın bir HSM'yi karşılayacak bütçesi yoktur. Yazılım anahtar depoları bir noktada anahtarı belleğe yüklemelidir, bu yüzden IMO en azından belleğinizin tekrar açılması durumunda seçeneğine sahip olmalıdır. - emboss
Kesinlikle, bir HSM'ye eşdeğer bazı yazılım uygulamalarının belleği temizlemede daha iyi davranıp çalışamayacağını merak ediyordum. Örneğin, Safari / OSX ile istemci-auth kullanırken, Safari işlemi hiçbir zaman özel anahtarı görmez; OS tarafından sağlanan temel SSL kütüphanesi, kullanıcıyı anahtar zincirinden anahtarı kullanmaya yönlendiren güvenlik arşivine doğrudan konuşur. Bu, her şey yazılıma yapılırken, benzer bir ayrım, imzalamanın, belleği daha iyi kaldıracak veya temizleyecek başka bir varlığa (hatta yazılım tabanlı) devredilmişse yardımcı olabilir. - Bruno
@Bruno: İlginç bir fikir, hafızayı temizlemeye özen gösteren ek bir dolaylı katman gerçekten bu sorunu çözecektir. Yazılım anahtarı deposu için bir PKCS # 11 sarmalayıcısı yazmanız zaten hile yapabilir mi? - emboss


Jon Skeet'in belirttiği gibi, yansıma kullanmanın dışında bir yolu yoktur.

Ancak, yansıma sizin için bir seçenekse, bunu yapabilirsiniz.

public static void main(String[] args) {
    System.out.println("please enter a password");
    // don't actually do this, this is an example only.
    Scanner in = new Scanner(System.in);
    String password = in.nextLine();
    usePassword(password);

    clearString(password);

    System.out.println("password: '" + password + "'");
}

private static void usePassword(String password) {

}

private static void clearString(String password) {
    try {
        Field value = String.class.getDeclaredField("value");
        value.setAccessible(true);
        char[] chars = (char[]) value.get(password);
        Arrays.fill(chars, '*');
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

koşarken

please enter a password
hello world
password: '***********'

Not: String'in char [] öğesi bir GC döngüsünün bir parçası olarak kopyalanmışsa, bir önceki kopyanın bellekte bir yeri vardır.

Bu eski kopya bir yığın dökümünde görünmez, ancak işlemin ham belleğine doğrudan erişirseniz onu görebilirsiniz. Genel olarak böyle bir erişimi olanlardan kaçınmalısınız.


41
2017-07-08 09:26



Bizden aldığımız şifre uzunluğunu yazdırmak için bir şeyler yapmak daha iyidir '***********'. - chux
@chux, sıfırdan genişlikli bir karakter kullanabilir, ancak bu yararlıdan daha kafa karıştırıcı olabilir. Güvenli olmayan kullanmadan bir char dizisinin uzunluğunu değiştirmek mümkün değildir. ;) - Peter Lawrey
Java 8'in String Deduplication'ı nedeniyle, sanırım böyle bir şey yapmanın oldukça yıkıcı olabileceğini düşünüyorum ... programınızdaki diğer dizeleri temizlemenizle sonuçlanabilir. Muhtemelen, ama mümkün ... - jamp
Jamp Java 9'un bu özelliğe ve kompakt dizeye (yani bir bayt []] kullanarak) sahip olması beklenir. Bunun Java 8'de olduğuna inanmıyorum. - Peter Lawrey
@PeterLawrey Bir JVM argümanı ile etkinleştirilmelidir, ancak o var. Burada okuyabilirsiniz: blog.codecentric.de/en/2014/08/... - jamp


Düzenle: Bir yıl süren bir güvenlik araştırmasından sonra bu cevaba geri döndüğümde, düz metin şifrelerini gerçekten karşılaştırdığın oldukça talihsiz bir anlam yarattığının farkındayım. Lütfen yapma. Bir tuz ve makul sayıda yineleme ile güvenli tek yönlü bir karı kullanın. Bir kütüphane kullanmayı düşünün: Bu şeyin doğru olması zor!

Orijinal cevap: String.equals () 'ın kullandığı gerçeğe ne dersiniz? kısa devre değerlendirmesive bu nedenle bir zamanlama saldırısına karşı savunmasız mı? Olası olmayabilir ama sen teorik olarak Doğru karakter sırasını belirlemek için şifre karşılaştırma zamanı.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        // Quits here if Strings are different lengths.
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // Quits here at first different character.
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Zamanlama saldırılarında daha fazla kaynak var:


32
2018-04-08 00:04



Ama bu aynı zamanda char [] karşılaştırmasında da olabilirdi, aynı zamanda şifre doğrulamada da aynısını yapardık. öyleyse char [] string'den nasıl daha iyi? - Mohit Kanwar
Kesinlikle haklısınız, hata her iki şekilde de yapılabilir. Problemin bilinmesi, burada, hem String hem de char [] - tabanlı parolalar için Java'da açık bir şifre karşılaştırma yöntemi bulunmadığı için en önemli şeydir. String () için compare () kullanmanın cazibesinin char [] ile gitmek için iyi bir neden olduğunu söyleyebilirim. Bu şekilde, en azından karşılaştırmanın nasıl yapıldığına dair kontrolünüz vardır (String imi olmadan, bir ağrı imo). - Graph Theory
Düz metin şifrelerini karşılaştırmanın yanı sıra, zaten doğru olan şey de doğru değil. Arrays.equals için char[] kadar yüksek String.equals. Eğer ilgilenen birileri varsa, gerçek şifreyi özümseyen ve sorunları ele alan özel bir anahtar sınıfı vardı - ah, bekle, gerçek güvenlik paketleri var adanmış anahtar sınıfları, bu Q & A sadece bir alışkanlık bunların dışında, ör. JPasswordField, kullanmak char[] yerine String (gerçek algoritmaların nerede kullanıldığı byte[] Neyse). - Holger
Güvenlik ile ilgili yazılım gibi bir şey yapmalı sleep(secureRandom.nextInt()) Yine de bir giriş denemesini reddetmeden önce, bu sadece zamanlama saldırılarının olasılığını ortadan kaldırmakla kalmaz, aynı zamanda kaba kuvvet girişimlerine de karşı koyar. - Holger


Bunların hepsi, birinin seçmesi gereken char [] yerine dizisi sicim şifre için

1.  Parolalar düz metin olarak depolanırsa, dizeler Java'da değişmez olduğundan, Çöp kutusu toplayıcıyı temizleyene kadar bellekte kullanılabilir ve yeniden kullanılabilirlik için Dize havuzunda Dize kullanıldığından, bellekte uzun süre kalması olasılığı oldukça yüksektir. Bu bir güvenlik tehdidi oluşturur. Bellek dökümünden yararlanan herhangi biri, şifreyi açık metin olarak bulabildiğinden ve bu da her zaman düz metinden daha fazla şifreli bir şifre kullanmanızın başka bir nedenidir. Dizeler değişmez olduğundan, herhangi bir değişiklik yeni String üreteceğinden, Strings'in içeriğinin değiştirilebileceği bir yol yoktur; eğer [] karakterini seçerseniz, tüm elemanını hala boş veya sıfır olarak ayarlayabilirsiniz. Bu nedenle, karakter dizisinde parola saklamak, parola çalma riskini açıkça azaltır.

2.  Java'nın kendisi bir char [] döndüren JPasswordField öğesinin getPassword () yöntemini kullanmasını ve güvenlik nedenini belirten açık metinde parola döndüren getText () yöntemini kullanım dışı bırakılmasını önerir. Java ekibinden tavsiye almak ve buna karşı çıkmak yerine standartlara uymak iyi.

3.  Dize ile günlük dosyasına veya konsola her zaman düz metin yazdırma riski vardır ancak Dizi kullanırsanız, dizinin içeriğini yazdırmazsınız, bunun yerine bellek konumu yazdırılır. gerçek bir sebep olmasa da yine de mantıklı.

    String strPassword="Unknown";
    char[] charPassword= new char[]{'U','n','k','w','o','n'};
    System.out.println("String password: " + strPassword);
    System.out.println("Character password: " + charPassword);

    String password: Unknown
    Character password: [C@110b053

Referans: http://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html Bu yardımcı olur umarım.


32
2018-05-08 10:17



Bu gereksiz. Bu cevap, @SrujanKumarGulla tarafından yazılan cevabın tam bir versiyonudur. stackoverflow.com/a/14060804/1793718. Lütfen yapıştırmayı kopyalamayın ya da aynı cevabı iki kez kopyalayın. - Lucky
1.) System.out.println ("Karakter şifresi:" + charPassword) arasındaki fark nedir; ve 2.) System.out.println (charPassword); Çünkü çıktı olarak aynı "bilinmeyen" veriyor. - Vaibhav_Sharma