Java'da String nasıl şifrelenir


154

İhtiyacım olan şey, 2D barkodda (PDF-417) görünecek olan dizeyi şifrelemek, böylece biri taramak için bir fikir geldiğinde okunabilir bir şey elde etmeyecek.

Diğer gereklilikler:

  • karmaşık olmamalı
  • RSA, PKI altyapısı, anahtar çiftleri vb. içermemelidir.

Etrafta dolaşan insanlardan kurtulmak yeterince basit olmalı ve bu verileri almakla ilgilenen diğer şirketler için şifresini çözmesi kolay olmalıdır. Bizi ararlar, onlara standardı söyleriz veya onlara şifre çözme için kullanılabilecek basit bir anahtar veririz.

Muhtemelen bu şirketler farklı teknolojiler kullanabilir, bu nedenle bazı özel platformlara veya teknolojilere bağlı olmayan bazı standartlara bağlı kalmak iyi olacaktır.

Sen ne önerirsin? Yüksek güvenlik standartlarına ulaşmak için herhangi bir Java sınıfı yapıyor encrypt()ve decrypt()fazla karmaşıklık olmadan var mı?



1
Uyarı . Aşağıdaki yanıtların çoğu , Java üzerinde herhangi bir kriptografi gerçekleştirmek için bir yöntemi veya diğerini göstermektedir . Cevapları olabilir iyi kriptografik uygulamalar yansıtmıyor ve olabilecek iyi incelenemeyecektir; kopyala / yapıştır güvenliği diye bir şey yoktur . Cevapları gerektiğini , en azından dikkate dize dönüşüm alır. 2D barkodun dahil olduğu asıl soru çok geniş ve müşteriye özel bir çözüm gerektirmelidir.
Maarten Bodewes

Yanıtlar:


168

Bu, Google aracılığıyla görünen ilk sayfadır ve tüm uygulamalardaki güvenlik açıkları beni rahatsız ediyor, bu yüzden orijinal gönderiden 7 Yıl sonra başkaları için şifreleme ile ilgili bilgi eklemek için bunu gönderiyorum . Bilgisayar Mühendisliği Yüksek Lisans derecesine sahibim ve Kriptografi okuyup öğrenmek için çok zaman harcadım, bu yüzden interneti daha güvenli bir yer haline getirmek için iki sentimi harcıyorum.

Ayrıca, belirli bir durum için birçok uygulamanın güvenli olabileceğini, ancak neden bunları kullanıp potansiyel olarak yanlışlıkla bir hata yapabileceğinizi unutmayın? Kullanmamak için belirli bir nedeniniz yoksa, sahip olduğunuz en güçlü araçları kullanın. Genel olarak bir kütüphane kullanmanızı ve mümkünse zorlu ayrıntılardan uzak durmanızı şiddetle tavsiye ederim.

GÜNCELLEME 4/5/18: Onları daha basit anlamak ve recommended kütüphane değişti yapmak için bazı bölümlerini yeniden yazdı Jasypt için Google'ın yeni kütüphanesinde Tink tamamen kaldırılması öneriyoruz, Jasypt varolan kurulumundan.

Önsöz

Aşağıda güvenli simetrik kriptografinin temellerini ana hatlarıyla açıklayacağım ve insanlar standart Java kitaplığı ile kriptoyu kendi başlarına uygularken çevrimiçi olarak gördüğüm yaygın hatalara işaret edeceğim. Google'ın yeni kitaplığına aktarılan tüm ayrıntıları atlamak istiyorsanız, Tink bunu projenize aktarın ve tüm şifrelemeleriniz için AES-GCM modunu kullanın ve güvende olacaksınız.

Şimdi, javada nasıl şifreleneceğine dair nitty cesur ayrıntıları öğrenmek istiyorsanız okumaya devam edin :)

Blok Şifreleri

İlk önce simetrik bir anahtar Blok Şifresi seçmeniz gerekir. Bir Blok Şifreleme, Sözde Rastgelelik oluşturmak için kullanılan bir bilgisayar işlevi / programıdır. Sözde Rastgelelik, Kuantum Bilgisayarı dışında hiçbir bilgisayarın onunla gerçek rastgelelik arasındaki farkı söyleyemeyeceği sahte rastgeleliktir. Block Cipher, kriptografinin yapı taşı gibidir ve farklı modlar veya şemalarla kullanıldığında şifreler oluşturabiliriz.

Şimdi bugün blok şifreleme algoritmaları kullanılabilir ilgili, emin olun asla , ben yinelerseniz ASLA kullanmak DES , ben bile kullanmak asla derdim 3DES . Snowden'ın NSA sürümünün bile Pseudo-Random'a olabildiğince yakın olduğunu doğrulayabildiği tek Blok Şifresi AES 256'dır . Ayrıca AES 128 vardır; aradaki fark, AES 256'nın 256 bitlik bloklar halinde, AES 128'in ise 128 blok halinde çalışmasıdır. Sonuç olarak, AES 128, bazı zayıflıklar keşfedilmiş olmasına rağmen güvenli olarak kabul edilir, ancak 256 olabildiğince sağlamdır.

Eğlenceli gerçek DES , ilk kurulduğunda NSA tarafından kırılmıştı ve aslında birkaç yıl boyunca bir sır olarak saklamıştı. Bazı insanlar hala iddia rağmen 3DES güvenlidir, zayıflıklar bulundu ve analiz ettik epeyce araştırma kağıtları vardır 3DES .

Şifreleme Modları

Şifreleme, bir blok şifresi aldığınızda ve belirli bir şema kullandığınızda oluşturulur, böylece anahtarı bildiğiniz sürece tersine çevrilebilir bir şey oluşturmak için rasgeleliğin bir anahtarla birleştirilmesi sağlanır. Buna Şifreleme Modu denir.

İşte bir şifreleme modu örneği ve ECB olarak bilinen en basit mod, ne olduğunu görsel olarak anlayabilmeniz için:

ECB Modu

İnternette en sık göreceğiniz şifreleme modları şunlardır:

ECB TO, CBC, GCM

Listelenenlerin dışında başka modlar da var ve araştırmacılar mevcut sorunları iyileştirmek için her zaman yeni modlar üzerinde çalışıyorlar.

Şimdi uygulamalara ve neyin güvenli olduğuna geçelim. ECB'yi ASLA kullanmayın, ünlü Linux pengueninin gösterdiği gibi, yinelenen verileri saklamakta kötüdür .Linux Penguin Örneği

Java'da uygularken, aşağıdaki kodu kullanırsanız, ECB modunun varsayılan olarak ayarlandığını unutmayın:

Cipher cipher = Cipher.getInstance("AES");

... TEHLİKE BU BİR KIRILMAZLIKTIR! ve ne yazık ki bu, tüm StackOverflow'da ve çevrimiçi olarak öğreticiler ve örneklerde görülmektedir.

Nonces ve IV'ler

ECB modu ile bulunan soruna yanıt olarak IV olarak da bilinen ibareler oluşturuldu. Buradaki fikir, yeni bir rastgele değişken oluşturmamız ve bunu her şifrelemeye eklememizdir, böylece aynı olan iki mesajı şifrelediğinizde farklı çıkarlar. Bunun arkasındaki güzellik, bir IV veya nonce'nin kamuya açık bilgi olmasıdır. Bu, bir saldırganın buna erişebileceği anlamına gelir, ancak anahtarınıza sahip olmadığı sürece, bu bilgiyle hiçbir şey yapamaz.

Göreceğim yaygın konular, insanların IV'ü, kodlarındaki aynı sabit değerde olduğu gibi statik bir değer olarak ayarlayacak olmalarıdır. ve işte IV'lerin tuzağı, birini tekrarladığınız anda şifrelemenizin tüm güvenliğini tehlikeye atıyorsunuz.

Rastgele IV Oluşturmak

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

Not: SHA1 bozuldu, ancak SHA256'yı bu kullanım senaryosuna nasıl düzgün bir şekilde uygulayacağımı bulamadım, bu yüzden herhangi biri bu konuda bir çatlak alıp güncelleme yapmak isterse harika olurdu! Ayrıca SHA1 saldırıları, büyük bir kümede kırılması birkaç yıl sürebileceğinden hala alışılmadık. Ayrıntılara buradan göz atın.

TO Uygulaması

TO modu için dolgu gerekmez.

 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

CBC Uygulaması

CBC Modunu uygulamayı seçerseniz, bunu PKCS7Padding ile aşağıdaki gibi yapın:

 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

CBC ve CTR Güvenlik Açığı ve GCM'yi Neden Kullanmalısınız?

CBC ve CTR gibi diğer bazı modlar güvenli olsa da, bir saldırganın şifrelenmiş verileri çevirip şifresi çözüldüğünde değerini değiştirebileceği sorunuyla karşılaşırlar. Diyelim ki hayali bir banka mesajını şifrelediniz, şifrelenmiş mesajınız şu "eu23ng" gibi görünüyor, saldırgan bir bit "eu53ng" olarak değişiyor ve mesajınızın şifresini çözdüğünde aniden "900 Sat" olarak okuyor.

Bunu önlemek için internetin çoğu GCM kullanıyor ve HTTPS'yi her gördüğünüzde muhtemelen GCM kullanıyorlar. GCM, şifrelenmiş mesajı bir hash ile imzalar ve mesajın bu imzayı kullanarak değiştirilmediğini kontrol eder.

Karmaşıklığı nedeniyle GCM'yi uygulamaktan kaçınırdım. Google’ın yeni kitaplığı Tink’i kullanmakta daha iyisiniz, çünkü burada yine yanlışlıkla IV’i tekrarlarsanız, en büyük güvenlik kusuru olan GCM’deki durumda anahtarı tehlikeye atmış olursunuz. Yeni araştırmacılar, IV'ü tekrarlasanız bile anahtarın tehlikede olmadığı ancak bu henüz ana akım haline gelmediği IV tekrar dirençli şifreleme modları üzerinde çalışıyorlar.

Şimdi, GCM'yi uygulamak istiyorsanız, işte güzel bir GCM uygulamasına bir bağlantı . Ancak, güvenliği sağlayamıyorum veya düzgün uygulanıyorsa, ancak temeli indiriyor. Ayrıca, GCM'de dolgu olmadığını unutmayın.

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

Anahtarlar ve Şifreler

Bir diğer önemli not da, kriptografi söz konusu olduğunda bir Anahtar ve Parola aynı şeyler değildir. Kriptografide bir Anahtarın güvenli olarak kabul edilebilmesi için belirli bir miktarda entropi ve rasgeleliğe sahip olması gerekir. Bu nedenle, sizin için anahtarı oluşturmak için uygun şifreleme kitaplıklarını kullandığınızdan emin olmanız gerekir.

Yani burada gerçekten yapabileceğiniz iki uygulama var, ilki bu StackOverflow iş parçacığında bulunan kodu Random Key Generation için kullanmaktır . Bu çözüm, kullanabileceğiniz sıfırdan bir anahtar oluşturmak için güvenli bir rastgele sayı üreteci kullanır.

Daha az güvenli olan diğer seçenek, şifre gibi kullanıcı girişi kullanmaktır. Tartıştığımız konu, şifrenin yeterli entropiye sahip olmamasıdır, bu nedenle şifreyi alan ve güçlendiren bir algoritma olan PBKDF2'yi kullanmak zorunda kalacağız . İşte sevdiğim bir StackOverflow uygulaması . Bununla birlikte, Google Tink kitaplığı tüm bunlara sahiptir ve bundan yararlanmalısınız.

Android Geliştiricileri

Burada belirtilmesi gereken önemli bir nokta, android kodunuzun tersine mühendisliğe tabi tutulabilir olduğunu ve çoğu durumda çoğu java kodunun da öyle olduğunu bilmektir. Bu, parolayı kodunuzda düz metin olarak saklamanız anlamına gelir. Bir bilgisayar korsanı onu kolayca bulabilir. Genellikle, bu tür şifreleme için Asimetrik Şifreleme vb. Kullanmak istersiniz. Bu, bu yazının kapsamı dışındadır, bu yüzden ona dalmaktan kaçınacağım.

Bir 2013 ilginç okuma : Android'de Kripto uygulamaların% 88 yanlış olduğu fikrine sahip Noktaları.

Son düşünceler

Bir kez daha java kitaplığını kripto için doğrudan uygulamaktan kaçınmanızı ve Google Tink'i kullanmanızı öneririm , tüm algoritmaları doğru bir şekilde uygulamak konusunda gerçekten iyi bir iş çıkardıkları için sizi baş ağrısından kurtaracaktır. Ve o zaman bile Tink github'da ortaya çıkan sorunları, burada ve orada güvenlik açıkları açılır penceresini kontrol ettiğinizden emin olun.

Herhangi bir sorunuz veya geri bildiriminiz varsa yorum yapmaktan çekinmeyin! Güvenlik sürekli değişiyor ve buna ayak uydurmak için elinizden gelenin en iyisini yapmanız gerekiyor :)


18
Bu şimdiye kadar gördüğüm en temiz şey.
Seraf

1
@SabirKhan Endişelenmek için bir neden olabilir ancak çekirdek algoritmalar hala kırılmadığı için bu konuda çok endişelenmem. Güvenmediğiniz durumda github.com/google/keyczar adresini de kontrol edin. Googles güvenlik ekibi tarafından geliştirilmiştir.
Konstantino Sparakis

1
@KonstantinoSparakis: Jasypt's BasicTextEncryptor ve StrongTextEncryptor belgelerini yanlış yorumlamadıysam, bu sınıflar şifreleme için DES ve 3DES kullanır, bu da okuyuculara kullanmamalarını söylediğiniz şeydir. IMO, verilen kod örneklerini Jasypt'in StandardPBEStringEncryptor'ını kullanan ve kullanılacak bir AES algoritmasını manuel olarak tanımlayan bir kodla değiştirmelisiniz.
xpages-noob

1
@ xpages-noob Gönderiyi güncelledim. Aslında kripto için desteklenen en yeni kitaplık olan Google Tink'i buldum, bu yüzden bir göz atmalısınız!
Konstantino Sparakis

2
AES blok boyutu 128 bittir. AES 256'da anahtar boyutu 256 bittir. Aynı şekilde AES 192 ve AES 128. Ayrıca Java 8'den beri SHA1PRNG'ye göre getInstanceStrong()yöntemi Ciphertercih edilir
Saptarshi Basu

110

DES , 3DES veya AES gibi yaygın olarak bulunabilen bazı standart simetrik şifreyi kullanmanızı tavsiye ederim . Bu en güvenli algoritma olmasa da, birçok uygulama var ve sadece barkoddaki bilgilerin şifresini çözmesi gereken herhangi birine anahtarı vermeniz gerekiyor. javax.crypto.Cipher , burada çalışmak istediğiniz şeydir.

Şifrelenecek baytların içinde olduğunu varsayalım

byte[] input;

Ardından, anahtara ve başlatma vektör baytlarına ihtiyacınız olacak

byte[] keyBytes;
byte[] ivBytes;

Şimdi, seçtiğiniz algoritmanın Şifresini başlatabilirsiniz:

// wrap key data in Key/IV specs to pass to cipher
SecretKeySpec key = new SecretKeySpec(keyBytes, "DES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
// create the cipher with the algorithm you choose
// see javadoc for Cipher class for more info, e.g.
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

Şifreleme şu şekilde olur:

cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted= new byte[cipher.getOutputSize(input.length)];
int enc_len = cipher.update(input, 0, input.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);

Ve şifre çözme şöyle:

cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(encrypted, 0, enc_len, decrypted, 0);
dec_len += cipher.doFinal(decrypted, dec_len);

9
DESedeAlgoritmaya başvurmak için bu örneği güncellemenizi önerebilir miyim ? Bu popüler bir soru (ve cevap) olduğu için, şifreleme günümüz standartlarına göre çok zayıf olduğu için insanları DES kullanmaya teşvik etmek utanç verici olurdu.
Duncan Jones

javax.crypto.BadPaddingException ile ilgili bir sorun var: Decript sırasında son blok düzgün şekilde doldurulmamışsa
merak

2
@Duncan Indeed DES zayıf ama sanırım AES, DESede'ye (diğer adıyla TipleDES) tercih edilir: http://security.stackexchange.com/a/26181/69785
Piovezan

2
Bu, AES / GCM / NoPadding'e sahip olacak şekilde güncellenmelidir, DES bruteforce saldırılarına karşı savunmasızdır, TripleDes de önerilmez
Konstantino Sparakis

1
Aşağıdaki Konstantino Sparakis'in cevabı bundan ÇOK daha iyi.
Steve

22

Uyarı

Bunu bir tür güvenlik ölçümü olarak kullanmayın.

Bu gönderideki şifreleme mekanizması, Tek seferlik bir peddir; bu, gizli anahtarın 2 şifreli mesaj kullanılarak bir saldırgan tarafından kolayca kurtarılabileceği anlamına gelir. XOR 2 şifreli mesajlar ve anahtarı alırsınız. Bu kadar basit!

Moussa tarafından işaret edildi


Sun'ın JRE'sinde bulunan Sun's Base64Encoder / Decoder'ı lib'de başka bir JAR'dan kaçınmak için kullanıyorum. Bu, OpenJDK veya başka birinin JRE'sini kullanma açısından tehlikelidir. Bunun yanı sıra, Apache commons lib'yi Encoder / Decoder ile birlikte kullanmayı düşünmem gereken başka bir neden var mı?

public class EncryptUtils {
    public static final String DEFAULT_ENCODING = "UTF-8"; 
    static BASE64Encoder enc = new BASE64Encoder();
    static BASE64Decoder dec = new BASE64Decoder();

    public static String base64encode(String text) {
        try {
            return enc.encode(text.getBytes(DEFAULT_ENCODING));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }//base64encode

    public static String base64decode(String text) {
        try {
            return new String(dec.decodeBuffer(text), DEFAULT_ENCODING);
        } catch (IOException e) {
            return null;
        }
    }//base64decode

    public static void main(String[] args) {
        String txt = "some text to be encrypted";
        String key = "key phrase used for XOR-ing";
        System.out.println(txt + " XOR-ed to: " + (txt = xorMessage(txt, key)));

        String encoded = base64encode(txt);       
        System.out.println(" is encoded to: " + encoded + " and that is decoding to: " + (txt = base64decode(encoded)));
        System.out.print("XOR-ing back to original: " + xorMessage(txt, key));
    }

    public static String xorMessage(String message, String key) {
        try {
            if (message == null || key == null) return null;

            char[] keys = key.toCharArray();
            char[] mesg = message.toCharArray();

            int ml = mesg.length;
            int kl = keys.length;
            char[] newmsg = new char[ml];

            for (int i = 0; i < ml; i++) {
                newmsg[i] = (char)(mesg[i] ^ keys[i % kl]);
            }//for i

            return new String(newmsg);
        } catch (Exception e) {
            return null;
        }
    }//xorMessage
}//class

1
Bu çözüm önerisini sun.misc.BASE64Encoder aracılığıyla da kullandım, ancak kodlamak için oldukça büyük dizeler kullanırken, kodlayıcı yığın halinde dizeler (her biri 76 karakter) döndürdü. Daha sonra yığın oluşturmayan kodlama yöntemleri sunan Apache Commons Codec Base64'e geçtim!
basZero

81
Tanımladığınız şifreleme mekanizması, birden fazla kullanıldığında ÇOK TEHLİKELİDİR. Tek kullanımlık ped olarak adlandırılmasının nedeni budur. Gizli anahtar, 2 şifreli mesaj kullanılarak bir saldırgan tarafından kolayca kurtarılabilir. xor 2 şifreli mesaj ve anahtarı alırsınız. Bu kadar basit!
xtrem

3
Fikri ağır olmak değil, sadece insanları PDF-417 2D barkodlarda yazılanları okumaya çalışmaktan kurtarmaktır. Ve her neyse, hiç kimse için önemli olmayan sadece bazı dizinler var ...
ante.sabo

2
TAMAM. Birinin bunu bir şifreleme mekanizması olarak kullanması endişesi.
xtrem

Şifreleme için, kodlayıcının (örn. BASE64Encoder) kaba kuvvet saldırılarına sahip olması engellenebilir.
Jagrut Dalwadi

13

Teşekkürler, bu sınıfı kodunuzu kullanarak yaptım belki birileri onu kullanışlıdır.

nesne şifreleyici

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;


public class ObjectCrypter {

private Cipher deCipher;
private Cipher enCipher;
private SecretKeySpec key;
private IvParameterSpec ivSpec;


public ObjectCrypter(byte[] keyBytes,   byte[] ivBytes) {
    // wrap key data in Key/IV specs to pass to cipher


     ivSpec = new IvParameterSpec(ivBytes);
    // create the cipher with the algorithm you choose
    // see javadoc for Cipher class for more info, e.g.
    try {
         DESKeySpec dkey = new  DESKeySpec(keyBytes);
          key = new SecretKeySpec(dkey.getKey(), "DES");
         deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
         enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public byte[] encrypt(Object obj) throws InvalidKeyException, InvalidAlgorithmParameterException, IOException, IllegalBlockSizeException, ShortBufferException, BadPaddingException {
    byte[] input = convertToByteArray(obj);
    enCipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);

    return enCipher.doFinal(input);




//  cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
//  byte[] encypted = new byte[cipher.getOutputSize(input.length)];
//  int enc_len = cipher.update(input, 0, input.length, encypted, 0);
//  enc_len += cipher.doFinal(encypted, enc_len);
//  return encypted;


}
public Object decrypt( byte[]  encrypted) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException {
    deCipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

    return convertFromByteArray(deCipher.doFinal(encrypted));

}



private Object convertFromByteArray(byte[] byteObject) throws IOException,
        ClassNotFoundException {
    ByteArrayInputStream bais;

    ObjectInputStream in;
    bais = new ByteArrayInputStream(byteObject);
    in = new ObjectInputStream(bais);
    Object o = in.readObject();
    in.close();
    return o;

}



private byte[] convertToByteArray(Object complexObject) throws IOException {
    ByteArrayOutputStream baos;

    ObjectOutputStream out;

    baos = new ByteArrayOutputStream();

    out = new ObjectOutputStream(baos);

    out.writeObject(complexObject);

    out.close();

    return baos.toByteArray();

}


}

burada ilgili bir soru yayınladı !
user2023507

Şifreleme ve şifre çözme sırasında farklı Anahtarların geçirilmesi metni geri döndürmemeli mi? Burada olmuyor gibi görünüyor. Not: Bu testi gerçekleştirmek için bu sınıfın farklı nesnelerini kullanıyorum.
instanceOfObject

7

Jasypt'i kullanabilirsin

Jasypt ile bir şifreyi şifrelemek ve kontrol etmek kadar basit olabilir ...

StrongTextEncryptor textEncryptor = new StrongTextEncryptor();
textEncryptor.setPassword(myEncryptionPassword);

Şifreleme:

String myEncryptedText = textEncryptor.encrypt(myText);

Şifre çözme:

String plainText = textEncryptor.decrypt(myEncryptedText);

Gradle:

compile group: 'org.jasypt', name: 'jasypt', version: '1.9.2'

Özellikleri:

Jasypt size kolay tek yönlü (özet) ve çift yönlü şifreleme teknikleri sağlar.

Yalnızca varsayılan Java VM olanı değil, herhangi bir JCE sağlayıcısıyla kullanım için açık API. Jasypt, Bouncy Castle gibi tanınmış sağlayıcılarla kolayca kullanılabilir. Daha fazla bilgi edin.

Kullanıcılarınızın şifreleri için daha yüksek güvenlik. Daha fazla bilgi edin.

İkili şifreleme desteği. Jasypt, ikili dosyaların (bayt dizileri) sindirilmesine ve şifrelenmesine izin verir. Nesnelerinizi veya dosyalarınızı gerektiğinde şifreleyin (örneğin ağ üzerinden gönderilmek için).

Numara şifreleme desteği. Metinler ve ikili dosyaların yanı sıra, sayısal değerlerin özetlenmesine ve şifrelenmesine izin verir (BigInteger ve BigDecimal, diğer sayısal türler Hazırda bekletme kalıcılığı için şifrelenirken desteklenir). Daha fazla bilgi edin.

Tamamen iş parçacığı güvenli.

Çok işlemcili / çok çekirdekli sistemlerde yüksek performans elde etmek için şifreleyici / çürütücü havuzu desteği.

Mobil platformlar gibi boyutu kısıtlayıcı ortamlarda daha iyi yönetilebilirlik için kitaplığın hafif ("hafif") bir sürümünü içerir.

Şifrelemeye yeni başlayan kullanıcılar için hem kolay, konfigürasyonsuz şifreleme araçları hem de ileri düzey kullanıcılar için oldukça yapılandırılabilir standart şifreleme araçları sağlar.

Eşlenen varlıklarınızın alanlarını şifreli bir şekilde sürdürmek için isteğe bağlı 3 ve 4 entegrasyonunu hazırda bekletme. Alanların şifrelenmesi, Hazırda Bekletme eşleme dosyalarında tanımlanır ve uygulamanın geri kalanı için şeffaf kalır (hassas kişisel veriler için yararlıdır, okuma özelliği olan birçok kullanıcıya sahip veritabanları ...). Metinleri, ikili dosyaları, sayıları, boole'leri, tarihleri ​​şifreleyin ... Daha fazla bilgi edinin.

Spring 2, Spring 3.0 ve Spring 3.1 için özel entegrasyon özellikleriyle bir Spring uygulamasına sorunsuz bir şekilde entegre edilebilir. Jasypt'deki tüm sindiriciler ve şifreleyiciler, Spring'den itibaren kolayca kullanılmak (örneklenmiş, bağımlılık enjekte edilmiş ...) için tasarlanmıştır. İş parçacığı açısından güvenli olmalarından dolayı, Spring gibi tek ton odaklı bir ortamda senkronizasyon endişesi olmadan kullanılabilirler. Daha fazla bilgi edinin: Spring 2, Spring 3.0, Spring 3.1.

Spring Security (eski adıyla Acegi Security), güvenlik çerçevesi için parola şifreleme ve eşleştirme görevleri gerçekleştirmek için isteğe bağlı entegrasyon, daha güvenli parola şifreleme mekanizmaları kullanarak kullanıcılarınızın parolalarının güvenliğini artırır ve size daha yüksek düzeyde yapılandırma ve denetim sağlar. Daha fazla bilgi edin.

Veritabanı şifreleri gibi hassas bilgiler dahil olmak üzere bir uygulamanın yapılandırma dosyalarının tamamını veya bir kısmını şifrelemek için gelişmiş işlevsellik sağlar. Şifrelenmiş yapılandırmayı düz, Yay tabanlı ve / veya Hazırda Bekletme özellikli uygulamalara sorunsuz bir şekilde entegre edin. Daha fazla bilgi edin.

Geliştiricilerin şifrelenmiş verilerini başlatmalarına ve bakım görevlerine veya komut dosyalarına şifreleme / şifre çözme / özet işlemlerini dahil etmelerine olanak tanıyan kullanımı kolay CLI (Komut Satırı Arayüzü) araçları sağlar. Daha fazla bilgi edin.

Güvenli uygulamalarınızda URL'lerin daha sağlam şifrelenmesi için Apache Wicket ile bütünleşir.

Geliştiricilerin verilerine gerçekte ne yaptıklarını daha iyi anlamalarını sağlamak için kapsamlı kılavuzlar ve javadoc belgeleri.

Orijinal karakter kümesinden hangisi olursa olsun, metinleri yeterince şifrelemek ve özümlemek için tasarlanmış sağlam karakter kümesi desteği. Japonca, Korece, Arapça gibi diller için kodlama veya platform sorunları olmadan tam destek.

Çok yüksek düzeyde yapılandırma yetenekleri: Geliştirici, bir "şifreleyiciye", örneğin şifreleme için kullanılacak parolayı uzak bir HTTPS sunucusuna sorması için talimat vermek gibi hileler uygulayabilir. Güvenlik ihtiyaçlarınızı karşılamanızı sağlar.


1
Ama ne güvenlik Jasyptsağlar? Web sitelerinden anlayamıyorum. Seçilmiş düz metin saldırıları altında ayırt edilemez mi? Bütünlük? Gizlilik?
trichner

7

12-ARALIK-2019 ile ilgili güncelleme

CBC gibi diğer bazı modların aksine, GCM modu IV'ün tahmin edilemez olmasını gerektirmez. Tek gereksinim, IV'ün belirli bir anahtarla her çağrı için benzersiz olması gerektiğidir. Belirli bir anahtar için bir kez tekrar ederse, güvenlik tehlikeye girebilir. Bunu başarmanın kolay bir yolu, aşağıda gösterildiği gibi güçlü bir sözde rastgele sayı oluşturucudan rastgele bir IV kullanmaktır.

IV olarak bir dizi veya zaman damgası kullanmak da mümkündür, ancak göründüğü kadar önemsiz olmayabilir. Örneğin, sistem kalıcı bir depoda IV olarak halihazırda kullanılan sekansları doğru bir şekilde takip etmezse, bir sistem yeniden başlatıldıktan sonra bir invokasyon bir IV'ü tekrarlayabilir. Aynı şekilde mükemmel bir saat de yoktur. Bilgisayar saati yeniden ayarlar vb.

Ayrıca, her 2 ^ 32 çağrıdan sonra anahtar döndürülmelidir. IV gereksinimi hakkında daha fazla ayrıntı için, bu yanıta ve NIST önerilerine bakın .


Bu, aşağıdaki noktaları göz önüne alarak Java 8'de yazdığım şifreleme ve şifre çözme kodudur. Umarım birisi bunu faydalı bulacaktır:

  1. Şifreleme Algoritması : 256 bit anahtarlı blok şifreleme AES, yeterince güvenli kabul edilir. Tam bir mesajı şifrelemek için bir modun seçilmesi gerekir. Doğrulanmış şifreleme (hem gizlilik hem de bütünlük sağlar) önerilir. GCM, CCM ve EAX en yaygın olarak kullanılan kimliği doğrulanmış şifreleme modlarıdır. GCM genellikle tercih edilir ve GCM için özel talimatlar sağlayan Intel mimarilerinde iyi performans gösterir. Bu üç modun tümü CTR tabanlı (sayaç tabanlı) modlardır ve bu nedenle doldurmaya ihtiyaç duymazlar. Sonuç olarak, doldurma ile ilgili saldırılara karşı savunmasız değiller

  2. GCM için bir başlatma Vektörü (IV) gereklidir. IV bir sır değil. Tek şart, rastgele veya öngörülemez olması. Java'da, SecuredRandomsınıfın kriptografik olarak güçlü sözde rastgele sayılar üretmesi amaçlanmıştır. Sözde rasgele sayı üretme algoritması, getInstance()yöntemde belirtilebilir . Bununla birlikte, Java 8'den beri, önerilen yol, getInstanceStrong()tarafından yapılandırılan ve sağlanan en güçlü algoritmayı kullanacak yöntemi kullanmaktır.Provider

  3. NIST, birlikte çalışabilirliği, verimliliği ve tasarım basitliğini teşvik etmek için GCM için 96 bit IV önerir

  4. Ek güvenlik sağlamak için, aşağıdaki uygulamada SecureRandomher 2 ^ 16 bayt sözde rastgele bayt üretildikten sonra yeniden tohumlama yapılır

  5. Alıcının şifre metninin şifresini çözebilmesi için IV'ü bilmesi gerekir. Bu nedenle IV'ün şifre metni ile birlikte aktarılması gerekir. Bazı uygulamalar IV'ü AD (İlişkili Veriler) olarak gönderir, bu da kimlik doğrulama etiketinin hem şifre metni hem de IV üzerinde hesaplanacağı anlamına gelir. Ancak bu gerekli değildir. IV, kasıtlı bir saldırı veya ağ / dosya sistemi hatası nedeniyle iletim sırasında değiştirilirse, kimlik doğrulama etiketi doğrulaması yine de başarısız olacağından, şifre metni ile basitçe önceden bekletilebilir.

  6. Dizeler değişmez olduğu için açık metin mesajını veya anahtarı tutmak için kullanılmamalıdır ve bu nedenle kullanımdan sonra bunları temizleyemeyiz. Bu temizlenmemiş Dizeler daha sonra hafızada kalır ve bir yığın dökümünde görünebilir. Aynı nedenden ötürü, bu şifreleme veya şifre çözme yöntemlerini çağıran istemci, mesajı veya anahtarı tutan tüm değişkenleri veya dizileri artık ihtiyaç kalmadığında temizlemelidir.

  7. Genel önerileri izleyen kodda hiçbir sağlayıcı sabit kodlu değildir

  8. Son olarak, ağ veya depolama üzerinden aktarım için, anahtar veya şifre metni Base64 kodlaması kullanılarak kodlanmalıdır. Base64'ün ayrıntıları burada bulunabilir . Java 8 yaklaşımı izlenmelidir

Bayt dizileri şu şekilde temizlenebilir:

Arrays.fill(clearTextMessageByteArray, Byte.MIN_VALUE);

Bununla birlikte, Java 8'den itibaren, temizlemenin kolay bir yolu yoktur SecretKeyspecve SecretKeybu iki arayüzün uygulamaları destroy()arayüz yöntemini uygulamış görünmemektedir Destroyable. Aşağıdaki kodda, yansımayı temizlemek SecretKeySpecve SecretKeykullanmak için ayrı bir yöntem yazılmıştır .

Anahtar, aşağıda belirtilen iki yaklaşımdan biri kullanılarak oluşturulmalıdır.

Anahtarların parolalar gibi sırlar olduğunu, ancak insan kullanımı için tasarlanmış parolalardan farklı olarak, anahtarların kriptografik algoritmalar tarafından kullanılması amaçlandığını ve bu nedenle yalnızca yukarıdaki yöntem kullanılarak oluşturulması gerektiğini unutmayın.

package com.sapbasu.javastudy;

import java.lang.reflect.Field;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Crypto {

  private static final int AUTH_TAG_SIZE = 128; // bits

  // NIST recommendation: "For IVs, it is recommended that implementations
  // restrict support to the length of 96 bits, to
  // promote interoperability, efficiency, and simplicity of design."
  private static final int IV_LEN = 12; // bytes

  // number of random number bytes generated before re-seeding
  private static final double PRNG_RESEED_INTERVAL = Math.pow(2, 16);

  private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";

  private static final List<Integer> ALLOWED_KEY_SIZES = Arrays
      .asList(new Integer[] {128, 192, 256}); // bits

  private static SecureRandom prng;

  // Used to keep track of random number bytes generated by PRNG
  // (for the purpose of re-seeding)
  private static int bytesGenerated = 0;

  public byte[] encrypt(byte[] input, SecretKeySpec key) throws Exception {

    Objects.requireNonNull(input, "Input message cannot be null");
    Objects.requireNonNull(key, "key cannot be null");

    if (input.length == 0) {
      throw new IllegalArgumentException("Length of message cannot be 0");
    }

    if (!ALLOWED_KEY_SIZES.contains(key.getEncoded().length * 8)) {
      throw new IllegalArgumentException("Size of key must be 128, 192 or 256");
    }

    Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);

    byte[] iv = getIV(IV_LEN);

    GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);

    cipher.init(Cipher.ENCRYPT_MODE, key, gcmParamSpec);
    byte[] messageCipher = cipher.doFinal(input);

    // Prepend the IV with the message cipher
    byte[] cipherText = new byte[messageCipher.length + IV_LEN];
    System.arraycopy(iv, 0, cipherText, 0, IV_LEN);
    System.arraycopy(messageCipher, 0, cipherText, IV_LEN,
        messageCipher.length);
    return cipherText;
  }

  public byte[] decrypt(byte[] input, SecretKeySpec key) throws Exception {
    Objects.requireNonNull(input, "Input message cannot be null");
    Objects.requireNonNull(key, "key cannot be null");

    if (input.length == 0) {
      throw new IllegalArgumentException("Input array cannot be empty");
    }

    byte[] iv = new byte[IV_LEN];
    System.arraycopy(input, 0, iv, 0, IV_LEN);

    byte[] messageCipher = new byte[input.length - IV_LEN];
    System.arraycopy(input, IV_LEN, messageCipher, 0, input.length - IV_LEN);

    GCMParameterSpec gcmParamSpec = new GCMParameterSpec(AUTH_TAG_SIZE, iv);

    Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
    cipher.init(Cipher.DECRYPT_MODE, key, gcmParamSpec);

    return cipher.doFinal(messageCipher);
  }

  public byte[] getIV(int bytesNum) {

    if (bytesNum < 1) throw new IllegalArgumentException(
        "Number of bytes must be greater than 0");

    byte[] iv = new byte[bytesNum];

    prng = Optional.ofNullable(prng).orElseGet(() -> {
      try {
        prng = SecureRandom.getInstanceStrong();
      } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("Wrong algorithm name", e);
      }
      return prng;
    });

    if (bytesGenerated > PRNG_RESEED_INTERVAL || bytesGenerated == 0) {
      prng.setSeed(prng.generateSeed(bytesNum));
      bytesGenerated = 0;
    }

    prng.nextBytes(iv);
    bytesGenerated = bytesGenerated + bytesNum;

    return iv;
  }

  private static void clearSecret(Destroyable key)
      throws IllegalArgumentException, IllegalAccessException,
      NoSuchFieldException, SecurityException {
    Field keyField = key.getClass().getDeclaredField("key");
    keyField.setAccessible(true);
    byte[] encodedKey = (byte[]) keyField.get(key);
    Arrays.fill(encodedKey, Byte.MIN_VALUE);
  }
}

Şifreleme anahtarı esas olarak iki şekilde oluşturulabilir:

  • Herhangi bir şifre olmadan

    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(KEY_LEN, SecureRandom.getInstanceStrong());
    SecretKey secretKey = keyGen.generateKey();
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
        "AES");
    Crypto.clearSecret(secretKey);
    // After encryption or decryption with key
    Crypto.clearSecret(secretKeySpec);
    
  • Şifre ile

    SecureRandom random = SecureRandom.getInstanceStrong();
    byte[] salt = new byte[32];
    random.nextBytes(salt);
    PBEKeySpec keySpec = new PBEKeySpec(password, salt, iterations, 
       keyLength);
    SecretKeyFactory keyFactory = 
        SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    SecretKey secretKey = keyFactory.generateSecret(keySpec);
    SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(),
        "AES");
    Crypto.clearSecret(secretKey);
    // After encryption or decryption with key
    Crypto.clearSecret(secretKeySpec);
    

Yorumlara Göre Güncelleme

@MaartenBodewes tarafından işaret edildiği gibi, cevabım sorunun Stringgerektirdiği gibi hiçbir şeyi ele almadı . Bu nedenle, birisi bu cevaba rastlarsa ve nasıl başa çıkılacağını merak etmeye başlarsa diye bu boşluğu doldurmaya çalışacağım String.

Yanıtta daha önce belirtildiği gibi, hassas bilgilerin a içinde ele alınması Stringgenel olarak iyi bir fikir değildir String, çünkü değişmezdir ve bu nedenle kullanımdan sonra onu temizleyemeyiz. Ve bildiğimiz gibi, Stringa güçlü bir referansı olmasa bile , çöp toplayıcı onu yığından çıkarmak için hemen acele etmez. Böylece, Stringprogram tarafından erişilebilir olmasa bile, bilinmeyen bir zaman penceresi boyunca bellekte kalmaya devam eder. Bununla ilgili sorun, bu zaman dilimi sırasında bir yığın dökümü hassas bilgileri ortaya çıkaracaktır. Bu nedenle, tüm hassas bilgileri bir bayt dizisinde veya karakter dizisinde işlemek ve daha sonra amaca hizmet ettikten sonra diziyi 0'larla doldurmak her zaman daha iyidir.

Bununla birlikte, tüm bu bilgilerle, şifrelenecek hassas bilginin bir içinde olduğu bir durumda Stringbulursak, önce onu bir bayt dizisine dönüştürmemiz encryptve decryptyukarıda tanıtılan ve işlevlerini çağırmamız gerekir . (Diğer giriş anahtarı, yukarıda verilen kod parçacığı kullanılarak oluşturulabilir).

A String, aşağıdaki şekilde bayta dönüştürülebilir:

byte[] inputBytes = inputString.getBytes(StandardCharsets.UTF_8);

Java 8 itibariyle, kodlama Stringile birlikte yığın halinde dahili olarak depolanır UTF-16. Ancak, özellikle ASCII karakterleri için UTF-8genellikle daha az yer kapladığından burada kullandık UTF-16.

Aynı şekilde, şifrelenmiş bayt dizisi de aşağıdaki gibi bir Dize'ye dönüştürülebilir:

String encryptedString = new String(encryptedBytes, StandardCharsets.UTF_8);

1
Mevcut kripto uygulamalarına bağlı kaldığı için bu yanıta oy vermek istesem de, hiçbir dizge işleme göremiyorum, bu da onu GCM modunun nasıl kullanılacağına dair bir açıklama gibi yapıyor. Bu nedenle soruyu cevaplayamaz .
Maarten Bodewes

2
@MaartenBodewes Görüşleri incelemek ve paylaşmak için zaman ayırdığınız için çok teşekkürler. Bunu, Stringyukarıda oluşturulan işlevleri kullanarak a şifrelemenin önemsiz olacağını anlayarak yazdım . Ancak, yorumunuzu okuduktan sonra ikinci bir bakışta bunun açık olmayabileceğini anlıyorum. Bu ayrıntıları eklemek için kesinlikle düzenleyeceğim.
Saptarshi Basu

4

Buna ne dersin:

private static byte[] xor(final byte[] input, final byte[] secret) {
    final byte[] output = new byte[input.length];
    if (secret.length == 0) {
        throw new IllegalArgumentException("empty security key");
    }
    int spos = 0;
    for (int pos = 0; pos < input.length; ++pos) {
        output[pos] = (byte) (input[pos] ^ secret[spos]);
        ++spos;
        if (spos >= secret.length) {
            spos = 0;
        }
    }
    return output;
}

Benim için iyi çalışıyor ve oldukça kompakt.


giriş parametresi secret == null veya input == null olursa ne olur? Dizelerle çalışmak yerine baytlarla çalışmak tamam, ama benim durumumda ilgisizdi .. önemli olan tek şey bunun herhangi bir cihazla, mümkün olan herhangi bir karakter kodlamasında okunabilir ve çözülebilir olması gerektiğidir ...
ante.sabo

@ ante.sabo görünüşe göre, bir NPE atacak. NULL'larla yapılacak tek şey budur.
Miha_x64

input.length <= secret.lengthHold ve no secrettekrar kullanılmadığı sürece bu güvenlidir ve a one-time-pad. Bu durumlarda input.length > secret.length, Vigenère şifresinin bir çeşididir ve çok zayıf kabul edilir.
trichner

4

İşte meta64.com'dan Spring Singleton olarak uygulamam. Her çağrı için aynı zamanda çalışacak bir ciper örneği oluşturmak istiyorsanız ve ardından 'senkronize edilmiş' çağrıları kaldırabilirsiniz, ancak 'şifre'nin iş parçacığı güvenli olmadığına dikkat edin.

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("singleton")
public class Encryptor {

    @Value("${aeskey}")
    private String keyStr;

    private Key aesKey = null;
    private Cipher cipher = null;

    synchronized private void init() throws Exception {
        if (keyStr == null || keyStr.length() != 16) {
            throw new Exception("bad aes key configured");
        }
        if (aesKey == null) {
            aesKey = new SecretKeySpec(keyStr.getBytes(), "AES");
            cipher = Cipher.getInstance("AES");
        }
    }

    synchronized public String encrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.ENCRYPT_MODE, aesKey);
        return toHexString(cipher.doFinal(text.getBytes()));
    }

    synchronized public String decrypt(String text) throws Exception {
        init();
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        return new String(cipher.doFinal(toByteArray(text)));
    }

    public static String toHexString(byte[] array) {
        return DatatypeConverter.printHexBinary(array);
    }

    public static byte[] toByteArray(String s) {
        return DatatypeConverter.parseHexBinary(s);
    }

    /*
     * DO NOT DELETE
     * 
     * Use this commented code if you don't like using DatatypeConverter dependency
     */
    // public static String toHexStringOld(byte[] bytes) {
    // StringBuilder sb = new StringBuilder();
    // for (byte b : bytes) {
    // sb.append(String.format("%02X", b));
    // }
    // return sb.toString();
    // }
    //
    // public static byte[] toByteArrayOld(String s) {
    // int len = s.length();
    // byte[] data = new byte[len / 2];
    // for (int i = 0; i < len; i += 2) {
    // data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i +
    // 1), 16));
    // }
    // return data;
    // }
}

3
Bu korkunç olan ECB modu ile şifrelenecektir. En azından CBC modunu veya GCM Modunu ayarlamalısınız
Konstantino Sparakis

Konstantinto önerisi için teşekkürler, Google'da araştırdım ve sadece "AES" yerine Cipher için Başlangıç ​​dizesi olarak "AES / CBC / PKCS5Padding" kullanan bazı kodlar buldum, ancak daha fazla araştıracağım. Veya isterseniz gerçek düzeltmeyi sağlayabilirsiniz, böylece diğerleri daha iyi yolu görebilir. Bununla birlikte, CBC ayrıntısının yanı sıra, çözümümün en basit ve en güvenli olduğuna ve diğerlerinin hepsinden önce yükseltilmeyi hak ettiğine inanıyorum.

Endişelenmeyin, Crypto karmaşık bir konudur. Ne yazık ki bu sayfadaki her uygulama bozuk ve maalesef google'ı "java şifreleme nasıl yapılır" araması için kullanırken açılan ilk sayfadır. Fırsat bulduğumda hepsini düzeltmeye çalışacağım.
Konstantino Sparakis

Örneğim şununla aynıdır: docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/… Cipher.getInstance'a ihtiyacım dışında ("AES / ECB / PKCS5Padding"); Kodum, 16 bayt uzunluğunda mükemmel bir şifreleme anahtarına sahip bazı özellikler dosyası olduğunu varsayar, ancak bir 'kullanıcı tarafından sağlanan' şifreden bir dizeyi şifrelemek için oracle sayfası (yukarıda bağlantılı) bunu yapmanın yolunu da gösterir.

1
Dolayısıyla, ECB ile ilgili sorun, frekans analizine karşı aşırı derecede savunmasız olmasıdır. Ünlü Linux penguen örneği var, blog.filippo.io/the-ecb-penguin görüntünün şifreli olmasına rağmen penguen olduğunu nasıl anlayabileceğinizi görün.
Devam ettim

4

Burada, gizlilik ve bütünlük sağlayan baytların şifrelenmesi için yalnızca java.*ve javax.crypto.*bağımlılıkları olan basit bir çözüm . Kilobayt sırasına göre kısa mesajlar için seçilmiş bir şifresiz metin saldırısı altında ayırt edilemez olacaktır .

O kullanır AESiçinde GCMbir 128bit anahtar elde edilir, hiçbir dolgu ile modundan PBKDF2sağlanan şifreden tekrarlamalar sürü ve statik tuz ile. Bu, kaba zorlama parolalarının zor olduğundan emin olur ve entropiyi tüm anahtara dağıtır.

Rastgele bir başlatma vektörü (IV) oluşturulur ve şifreli metnin başına eklenir. Ayrıca, statik bayt 0x01bir 'sürüm' olarak ilk bayt olarak başına eklenir.

Tüm mesaj, tarafından oluşturulan mesaj kimlik doğrulama koduna (MAC) gider AES/GCM.

İşte gizlilik ve bütünlük sağlayan sıfır harici bağımlılık şifreleme sınıfı :

package ch.n1b.tcrypt.utils;

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * This class implements AES-GCM symmetric key encryption with a PBKDF2 derived password.
 * It provides confidentiality and integrity of the plaintext.
 *
 * @author Thomas Richner
 * @created 2018-12-07
 */
public class AesGcmCryptor {

    // /crypto/26783/ciphertext-and-tag-size-and-iv-transmission-with-aes-in-gcm-mode
    private static final byte VERSION_BYTE = 0x01;
    private static final int VERSION_BYTE_LENGTH = 1;
    private static final int AES_KEY_BITS_LENGTH = 128;


    // fixed AES-GCM constants
    private static final String GCM_CRYPTO_NAME = "AES/GCM/NoPadding";
    private static final int GCM_IV_BYTES_LENGTH = 12;
    private static final int GCM_TAG_BYTES_LENGTH = 16;

    // can be tweaked, more iterations = more compute intensive to brute-force password
    private static final int PBKDF2_ITERATIONS = 1024;

    // protects against rainbow tables
    private static final byte[] PBKDF2_SALT = hexStringToByteArray("4d3fe0d71d2abd2828e7a3196ea450d4");

    public String encryptString(char[] password, String plaintext) throws CryptoException {

        byte[] encrypted = null;
        try {
            encrypted = encrypt(password, plaintext.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException //
                | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException //
                | InvalidKeySpecException e) {
            throw new CryptoException(e);
        }
        return byteArrayToHexString(encrypted);
    }

    public String decryptString(char[] password, String ciphertext)
            throws CryptoException {

        byte[] ct = hexStringToByteArray(ciphertext);
        byte[] plaintext = null;
        try {
            plaintext = decrypt(password, ct);
        } catch (AEADBadTagException e) {
            throw new CryptoException(e);
        } catch ( //
                NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException //
                        | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException //
                        | BadPaddingException e) {
            throw new CryptoException(e);
        }
        return new String(plaintext, StandardCharsets.UTF_8);
    }

    /**
     * Decrypts an AES-GCM encrypted ciphertext and is
     * the reverse operation of {@link AesGcmCryptor#encrypt(char[], byte[])}
     *
     * @param password   passphrase for decryption
     * @param ciphertext encrypted bytes
     * @return plaintext bytes
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws InvalidKeySpecException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws IllegalArgumentException           if the length or format of the ciphertext is bad
     * @throws CryptoException
     */
    public byte[] decrypt(char[] password, byte[] ciphertext)
            throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {

        // input validation
        if (ciphertext == null) {
            throw new IllegalArgumentException("ciphertext cannot be null");
        }

        if (ciphertext.length <= VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH + GCM_TAG_BYTES_LENGTH) {
            throw new IllegalArgumentException("ciphertext too short");
        }

        // the version must match, we don't decrypt other versions
        if (ciphertext[0] != VERSION_BYTE) {
            throw new IllegalArgumentException("wrong version: " + ciphertext[0]);
        }

        // input seems legit, lets decrypt and check integrity

        // derive key from password
        SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);

        // init cipher
        Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
        GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8,
                ciphertext,
                VERSION_BYTE_LENGTH,
                GCM_IV_BYTES_LENGTH
        );
        cipher.init(Cipher.DECRYPT_MODE, key, params);

        final int ciphertextOffset = VERSION_BYTE_LENGTH + GCM_IV_BYTES_LENGTH;

        // add version and IV to MAC
        cipher.updateAAD(ciphertext, 0, ciphertextOffset);

        // decipher and check MAC
        return cipher.doFinal(ciphertext, ciphertextOffset, ciphertext.length - ciphertextOffset);
    }

    /**
     * Encrypts a plaintext with a password.
     * <p>
     * The encryption provides the following security properties:
     * Confidentiality + Integrity
     * <p>
     * This is achieved my using the AES-GCM AEAD blockmode with a randomized IV.
     * <p>
     * The tag is calculated over the version byte, the IV as well as the ciphertext.
     * <p>
     * Finally the encrypted bytes have the following structure:
     * <pre>
     *          +-------------------------------------------------------------------+
     *          |         |               |                             |           |
     *          | version | IV bytes      | ciphertext bytes            |    tag    |
     *          |         |               |                             |           |
     *          +-------------------------------------------------------------------+
     * Length:     1B        12B            len(plaintext) bytes            16B
     * </pre>
     * Note: There is no padding required for AES-GCM, but this also implies that
     * the exact plaintext length is revealed.
     *
     * @param password  password to use for encryption
     * @param plaintext plaintext to encrypt
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws NoSuchPaddingException
     * @throws InvalidAlgorithmParameterException
     * @throws InvalidKeyException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidKeySpecException
     */
    public byte[] encrypt(char[] password, byte[] plaintext)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException,
            InvalidKeySpecException {

        // initialise random and generate IV (initialisation vector)
        SecretKey key = deriveAesKey(password, PBKDF2_SALT, AES_KEY_BITS_LENGTH);
        final byte[] iv = new byte[GCM_IV_BYTES_LENGTH];
        SecureRandom random = SecureRandom.getInstanceStrong();
        random.nextBytes(iv);

        // encrypt
        Cipher cipher = Cipher.getInstance(GCM_CRYPTO_NAME);
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_BYTES_LENGTH * 8, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);

        // add IV to MAC
        final byte[] versionBytes = new byte[]{VERSION_BYTE};
        cipher.updateAAD(versionBytes);
        cipher.updateAAD(iv);

        // encrypt and MAC plaintext
        byte[] ciphertext = cipher.doFinal(plaintext);

        // prepend VERSION and IV to ciphertext
        byte[] encrypted = new byte[1 + GCM_IV_BYTES_LENGTH + ciphertext.length];
        int pos = 0;
        System.arraycopy(versionBytes, 0, encrypted, 0, VERSION_BYTE_LENGTH);
        pos += VERSION_BYTE_LENGTH;
        System.arraycopy(iv, 0, encrypted, pos, iv.length);
        pos += iv.length;
        System.arraycopy(ciphertext, 0, encrypted, pos, ciphertext.length);

        return encrypted;
    }

    /**
     * We derive a fixed length AES key with uniform entropy from a provided
     * passphrase. This is done with PBKDF2/HMAC256 with a fixed count
     * of iterations and a provided salt.
     *
     * @param password passphrase to derive key from
     * @param salt     salt for PBKDF2 if possible use a per-key salt, alternatively
     *                 a random constant salt is better than no salt.
     * @param keyLen   number of key bits to output
     * @return a SecretKey for AES derived from a passphrase
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private SecretKey deriveAesKey(char[] password, byte[] salt, int keyLen)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        if (password == null || salt == null || keyLen <= 0) {
            throw new IllegalArgumentException();
        }
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        KeySpec spec = new PBEKeySpec(password, salt, PBKDF2_ITERATIONS, keyLen);
        SecretKey pbeKey = factory.generateSecret(spec);

        return new SecretKeySpec(pbeKey.getEncoded(), "AES");
    }

    /**
     * Helper to convert hex strings to bytes.
     * <p>
     * May be used to read bytes from constants.
     */
    private static byte[] hexStringToByteArray(String s) {

        if (s == null) {
            throw new IllegalArgumentException("Provided `null` string.");
        }

        int len = s.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Invalid length: " + len);
        }

        byte[] data = new byte[len / 2];
        for (int i = 0; i < len - 1; i += 2) {
            byte b = (byte) toHexDigit(s, i);
            b <<= 4;
            b |= toHexDigit(s, i + 1);
            data[i / 2] = b;
        }
        return data;
    }

    private static int toHexDigit(String s, int pos) {
        int d = Character.digit(s.charAt(pos), 16);
        if (d < 0) {
            throw new IllegalArgumentException("Cannot parse hex digit: " + s + " at " + pos);
        }
        return d;
    }

    private static String byteArrayToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    public class CryptoException extends Exception {

        public CryptoException(Throwable cause) {
            super(cause);
        }
    }
}

İşte güzel bir CLI ile tüm proje: https://github.com/trichner/tcrypt

Düzenleyin: şimdi uygun encryptStringvedecryptString


Bu inanılmaz. Teşekkür ederim! Kodunuzdan çok şey öğrendim ve BadVersionException Exception sınıfını oluşturduktan sonra kodunuz ilk seferinde mükemmel çalıştı. Mükemmel!!
Morkus

Bu girişimi beğendim. Dedi ki ... Tuz rastgele olmalı, statik değil. Yinelemeler muhtemelen statik de olmamalıdır. GCM, etiketin hesaplanmasında IV'ü zaten içerir. Yine de sürüm numarasını içermiyor. Taşınabilirlik için sağlayıcıyı belirtmemelisiniz, "SunJCE", onu destekleyen platformlarda varsayılan olacaktır. Bu kod, bu belirli soru için gerekli olan herhangi bir mesaj dizisi işleme içermez .
Maarten Bodewes

Pekala, biraz daha temizledim ve istenen encryptStringve decryptString:)
trichner

Bu çok iyi çalıştı; kod için ty. Bu kodun düzgün çalışması için API 19 (Kit Kat) veya üstü gerektirdiği unutulmamalıdır.
PGMacDesign

3

Https://www.bouncycastle.org/ gibi bir şey kullanmayı düşünürdüm Bu, istediğiniz her şeyi bir dizi farklı Şifreleme ile şifrelemenize izin veren önceden oluşturulmuş bir kitaplıktır, anlıyorum ki, yalnızca gözetlemekten korunmak istiyorsunuz, ancak gerçekten Bilgiyi korumak istiyorsanız, Base64 kullanmak sizi gerçekten korumaz.


1
Sadece şifreli rastgele bir kripto kitaplığı önermek, sorunun cevabı değil. Bunun yanı sıra, neden yerleşik şifreleri kullanmıyorsunuz?
Maarten Bodewes

2

İşte Java'nın desteklediklerini okuyabileceğiniz bazı bağlantılar

Bir veri akışının şifrelenmesi / şifresinin çözülmesi.

Bu örnek, büyük miktarda verinin nasıl şifreleneceğini (AES, Blowfish, RC2, 3DES vb. Gibi simetrik bir şifreleme algoritması kullanarak) gösterir. Veriler parçalar halinde şifreleme yöntemlerinden birine aktarılır: EncryptBytes, EncryptString, EncryptBytesENC veya EncryptStringENC. (Yöntem adı, girdi türünü (dize veya bayt dizisi) ve dönüş türünü (kodlanmış dize veya bayt dizisi) gösterir. FirstChunk ve LastChunk özellikleri, bir akışta bir öbeğin ilk, orta veya son olduğunu belirtmek için kullanılır Varsayılan olarak hem FirstChunk hem de LastChunk, true değerine eşittir - bu, aktarılan verilerin tüm miktar olduğu anlamına gelir.

JCERefGuide

Java Şifreleme Örnekleri


Evet, Java tarafından desteklenen kriptografi var. Bir akışın şifrelenmesi de istenen şey değildir.
Maarten Bodewes

2

Birçok kişinin daha önce söylediği gibi, DES veya AES gibi aşırı kullanılan standart bir şifre kullanmalısınız.

AES kullanarak java'da bir dizeyi nasıl şifreleyebileceğiniz ve şifresini çözebileceğinize dair basit bir örnek .

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EncryptorDemo {

    public static String encrypt(String key, String randomVector, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted text: "  + Base64.encodeBase64String(encrypted));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key, String randomVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(randomVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] originalText = cipher.doFinal(Base64.decodeBase64(encrypted));
            System.out.println("decrypted text: "  + new String(originalText));
            return new String(originalText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        String key = "JavasEncryptDemo"; // 128 bit key
        String randomVector = "RandomJavaVector"; // 16 bytes IV
        decrypt(key, randomVector, encrypt(key, randomVector, "Anything you want to encrypt!"));

    }
}

CBC artık güvenli bir mod değil. Dolgu, Oracle saldırılarının doldurulmasına karşı savunmasızdır. Ayrıca, String'de anahtar ve mesajların işlenmesi güvenli değildir. Dize havuzunda
oyalanacaklar

2
Yorum için minnettarım. Bu, kullanıcının sorduğu Java'nın şifreleme ve şifre çözme yöntemlerinin basit bir örneğiydi. Soru yaklaşık 9 yıl önce sorulmuş ve buna göre cevaplanmıştır. Teşekkürler.
viveknaskar

2
Evet, bu, şifreleme / şifre çözme işlemini başlatmanın basit bir yolu gibi görünüyor. Benim için bir cazibe gibi çalıştı .... Teşekkürler.
Codewrapper

0

İşte bir kopyala / yapıştır çözümü. Ayrıca , herhangi bir kod sağlamasa da @ Konstantino'nun cevabını okumanızı ve oylamanızı tavsiye ederim . Başlatma vektörü (IV) bir tuz gibidir - gizli tutulması gerekmez. GCM'de yeniyim ve görünüşe göre AAD isteğe bağlı ve yalnızca belirli durumlarda kullanılıyor. Anahtarı ortam değişkeninde ayarlayın SECRET_KEY_BASE. 32 karakterli bir şifre oluşturmak için KeePass gibi bir şey kullanın . Bu çözüm, Ruby çözümümden sonra modellenmiştir.

    public static String encrypt(String s) {
        try {
            byte[] input = s.getBytes("UTF-8");
            String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
            if (keyString == null || keyString.length() == 0) {
                Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
                return null;
            }
            byte[] keyBytes = keyString.getBytes("UTF-8");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            // generate IV
            SecureRandom secureRandom = SecureRandom.getInstanceStrong();
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] ivBytes = new byte[cipher.getBlockSize()];
            secureRandom.nextBytes(ivBytes);
            GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes); // 96 bit tag length
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
            // generate AAD
//          byte[] aadBytes = new byte[cipher.getBlockSize()];
//          secureRandom.nextBytes(aadBytes);
//          cipher.updateAAD(aadBytes);
            // encrypt
            byte[] encrypted = cipher.doFinal(input);
            byte[] returnBytes = new byte[ivBytes.length + encrypted.length];
//          byte[] returnBytes = new byte[ivBytes.length + aadBytes.length + encrypted.length];
            System.arraycopy(ivBytes, 0, returnBytes, 0, ivBytes.length);
//          System.arraycopy(aadBytes, 0, returnBytes, ivBytes.length, aadBytes.length);
            System.arraycopy(encrypted, 0, returnBytes, ivBytes.length, encrypted.length);
//          System.arraycopy(encrypted, 0, returnBytes, ivBytes.length+aadBytes.length, encrypted.length);
            String encryptedString = Base64.getEncoder().encodeToString(returnBytes);
            return encryptedString;
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | 
                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            Logger.error(Utils.class, "encrypt()", "Could not encrypt string: " + e.getMessage());
            return null;
        }
    }

    public static String decrypt(String s) {
        if (s == null || s.length() == 0) return "";
        try {
            byte[] encrypted = Base64.getDecoder().decode(s);
            String keyString = System.getProperty("SECRET_KEY_BASE", System.getenv("SECRET_KEY_BASE"));
            if (keyString == null || keyString.length() == 0) {
                Logger.error(Utils.class, "encrypt()", "$SECRET_KEY_BASE is not set.");
                return null;
            }
            byte[] keyBytes = keyString.getBytes("UTF-8");
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] ivBytes = new byte[cipher.getBlockSize()];
            System.arraycopy(encrypted, 0, ivBytes, 0, ivBytes.length);
            GCMParameterSpec gcmSpec = new GCMParameterSpec(96, ivBytes);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
//          cipher.updateAAD(encrypted, ivBytes.length, cipher.getBlockSize());
            byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize(), encrypted.length - cipher.getBlockSize());
//          byte[] decrypted = cipher.doFinal(encrypted, cipher.getBlockSize()*2, encrypted.length - cipher.getBlockSize()*2);
            String decryptedString = new String(decrypted, "UTF-8");
            return decryptedString;
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | UnsupportedEncodingException | InvalidKeyException | 
                InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            Logger.error(Utils.class, "decrypt()", "Could not decrypt string: " + e.getMessage());
            return null;
        }
    }

İşte bir örnek:

    String s = "This is a test.";
    String enc = Utils.encrypt(s);
    System.out.println(enc);
    // fQHfYjbD+xAuN5XzH2ojk/EWNeKXUrKRSfx8LU+5dpuKkM/pueCMBjKCZw==
    String dec = Utils.decrypt(enc);
    System.out.println(dec);
    // This is a test.

-4

Şifreleme / şifre çözme kodu üretimi yapmak için bazı otomatik araçları düşünebilirsiniz. https://www.stringencrypt.com/java-encryption/

Dize veya dosya şifrelemesi için her seferinde farklı şifreleme ve şifre çözme kodu oluşturabilir.

RSA, AES vb. Kullanmadan hızlı dize şifreleme söz konusu olduğunda oldukça kullanışlıdır.

Örnek sonuçlar:

// encrypted with https://www.stringencrypt.com (v1.1.0) [Java]
// szTest = "Encryption in Java!"
String szTest = "\u9E3F\uA60F\uAE07\uB61B\uBE1F\uC62B\uCE2D\uD611" +
                "\uDE03\uE5FF\uEEED\uF699\uFE3D\u071C\u0ED2\u1692" +
                "\u1E06\u26AE\u2EDC";

for (int iatwS = 0, qUJQG = 0; iatwS < 19; iatwS++)
{
        qUJQG = szTest.charAt(iatwS);
        qUJQG ++;
        qUJQG = ((qUJQG << 5) | ( (qUJQG & 0xFFFF) >> 11)) & 0xFFFF;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 6) | (qUJQG << 10)) & 0xFFFF;
        qUJQG ^= iatwS;
        qUJQG -= iatwS;
        qUJQG = (((qUJQG & 0xFFFF) >> 3) | (qUJQG << 13)) & 0xFFFF;
        qUJQG ^= 0xFFFF;
        qUJQG ^= 0xB6EC;
        qUJQG = ((qUJQG << 8) | ( (qUJQG & 0xFFFF) >> 8)) & 0xFFFF;
        qUJQG --;
        qUJQG = (((qUJQG & 0xFFFF) >> 5) | (qUJQG << 11)) & 0xFFFF;
        qUJQG ++;
        qUJQG ^= 0xFFFF;
        qUJQG += iatwS;
        szTest = szTest.substring(0, iatwS) + (char)(qUJQG & 0xFFFF) + szTest.substring(iatwS + 1);
}

System.out.println(szTest);

Şirketimizde her zaman kullanıyoruz.


Bu, belirsizlik yoluyla güvenliktir ve gerçekten güvenli değildir.
Chloe

Bu soru, dizelerin statik olarak çıkarılmasını zorlaştırmak için sadece gizlemeyi değil, AES gibi gerçek modern kriptografik güçte şifreleme istiyor. Bu, karakterler arasındaki herhangi bir durumu koruyor gibi görünmüyor, bu yüzden frekans analizine duyarlı. ( Latin alfabesi yerine UTF-16 kod noktaları dışında tek alfabe ikame şifresi . Ancak İngilizce ASCII metninde kullanırsanız, bunu yanlış okumadığım sürece yalnızca birkaç benzersiz 16 bit karakter değeri alırsınız)
Peter Cordes

-4
String s1="arshad"; 
char[] s2=s1.toCharArray(); 
int s3= s2.length; 

  System.out.println(s3);
 int i=0; 

// for(int j=0;j<s3;j++) 
// System.out.println(s2[j]); 

for(i=0;i<((s3)/2);i++) { 

char z,f=10; 
z=(char) (s2[i] * f); 
s2[i]=s2[(s3-1)-i]; 
s2[(s3-1)-i]=z; 

String b=new String(s2);

 print(b);  }

Biçimsel olarak verileri okunamaz bir biçimde şifreler. Şifresini çözmek için aynı kodu kullanın. Ve s [i] * f'yi s [I] / f olarak değiştirin.
Arshad shaik

Bu, belirsizlik yoluyla güvenliktir ve gerçekten güvenli değildir.
Chloe

-5
public static String encryptParams(String myTextInput) {

        String myKey = "40674244454045cb9a70040a30e1c007";
        String myVector = "@1B2c3D4e5F6g7H8";

        String encData = "";

        try{
            JavaEncryprtionUtil encUtil = new JavaEncryprtionUtil();
            encData = Base64.encodeToString(encUtil.encrypt(myTextInput.getBytes("UTF-8"), myKey.getBytes("UTF-8"), myVector.getBytes("UTF-8")),Base64.DEFAULT);
            System.out.println(encData);
        }catch(NoSuchAlgorithmException ex){
            ex.printStackTrace();
        }catch(NoSuchPaddingException ex){
            ex.printStackTrace();
        }catch(InvalidKeyException ex){
            ex.printStackTrace();
        }catch(InvalidAlgorithmParameterException ex){
            ex.printStackTrace();
        }catch(IllegalBlockSizeException ex){
            ex.printStackTrace();
        }catch(BadPaddingException ex){
            ex.printStackTrace();
        }catch(UnsupportedEncodingException ex){
            ex.printStackTrace();
        }

        return encData;
    }

1
JavaEncryprtionUtil, JDK API'nin bir parçası mı? değilse kütüphanenin adını hecelemelisiniz.
Fermat'ın Küçük Öğrencisi

4
O sınıfı bulamıyorum. Cevap uydurulmuş gibi geliyor.
james.garriss
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.