Yang saya butuhkan adalah mengenkripsi string yang akan ditampilkan dalam barcode 2D (PDF-417) sehingga ketika seseorang mendapatkan ide untuk memindai, tidak akan ada yang bisa dibaca.
Persyaratan lainnya:
- seharusnya tidak rumit
- tidak boleh terdiri dari RSA, infrastruktur PKI, pasangan kunci, dll.
Itu harus cukup sederhana untuk menyingkirkan orang yang mengintip, dan mudah didekripsi untuk perusahaan lain yang tertarik untuk mendapatkan data itu. Mereka memanggil kami, kami memberi tahu mereka standar atau memberi mereka beberapa kunci sederhana yang kemudian dapat digunakan untuk dekripsi.
Mungkin perusahaan-perusahaan itu dapat menggunakan teknologi yang berbeda sehingga akan baik untuk tetap berpegang pada standar yang tidak terikat pada platform atau teknologi khusus.
Apa yang Anda sarankan? Apakah ada kelas Java yang melakukan encrypt()
& decrypt()
tanpa banyak kesulitan dalam mencapai standar keamanan yang tinggi?
sumber
Jawaban:
Kata pengantar
Saya akan menguraikan dasar-dasar kriptografi simetris aman di bawah ini dan menunjukkan kesalahan umum yang saya lihat online ketika orang mengimplementasikan kripto sendiri dengan perpustakaan Java standar. Jika Anda ingin melewatkan semua detail yang berlarian ke perpustakaan baru Google, impor Tink itu ke proyek Anda dan gunakan mode AES-GCM untuk semua enkripsi Anda dan Anda akan aman.
Sekarang jika Anda ingin mempelajari rincian seluk beluk tentang cara mengenkripsi di java baca terus :)
Blokir Cipher
Hal pertama yang pertama Anda perlu memilih kunci simetris Block Cipher. Block Cipher adalah fungsi / program komputer yang digunakan untuk membuat Pseudo-Randomness. Pseudo-Randomness adalah keacakan palsu yang tidak ada komputer selain dari Komputer Quantum yang dapat membedakan antara itu dan keacakan nyata. Block Cipher adalah seperti blok penyusun untuk kriptografi, dan ketika digunakan dengan mode atau skema berbeda kita dapat membuat enkripsi.
Sekarang mengenai Block Cipher Algorithms yang tersedia hari ini, Pastikan untuk TIDAK PERNAH , saya ulangi TIDAK PERNAH menggunakan DES , saya bahkan akan mengatakan TIDAK PERNAH menggunakan 3DES . Satu-satunya Block Cipher yang bahkan rilis NSA Snowden mampu memverifikasi benar-benar sedekat mungkin dengan Pseudo-Random adalah AES 256 . Ada juga AES 128; perbedaannya adalah AES 256 bekerja di blok 256-bit, sedangkan AES 128 bekerja di 128 blok. Secara keseluruhan, AES 128 dianggap aman meskipun beberapa kelemahan telah ditemukan, tetapi 256 sekuat yang didapat.
Fakta asyiknya DES dihancurkan oleh NSA ketika awalnya didirikan dan benar-benar dirahasiakan selama beberapa tahun. Meskipun beberapa orang masih mengklaim 3DES aman, ada beberapa makalah penelitian yang telah menemukan dan menganalisis kelemahan dalam 3DES .
Mode Enkripsi
Enkripsi dibuat ketika Anda mengambil cipher blok dan menggunakan skema tertentu sehingga keacakan dikombinasikan dengan kunci untuk menciptakan sesuatu yang dapat dibalik selama Anda tahu kuncinya. Ini disebut sebagai Mode Enkripsi.
Berikut adalah contoh mode enkripsi dan mode paling sederhana yang dikenal sebagai ECB supaya Anda dapat memahami apa yang sedang terjadi secara visual:
Mode enkripsi yang paling sering Anda lihat online adalah sebagai berikut:
RKPT ECB, CBC, GCM
Ada mode lain di luar yang terdaftar dan peneliti selalu bekerja menuju mode baru untuk memperbaiki masalah yang ada.
Sekarang mari kita beralih ke implementasi dan apa yang aman. JANGAN PERNAH menggunakan ECB ini buruk menyembunyikan data berulang seperti yang ditunjukkan oleh penguin Linux yang terkenal .
Saat menerapkan di Java, perhatikan bahwa jika Anda menggunakan kode berikut, mode ECB diatur secara default:
... BAHAYA INI ADALAH KERENTANAN! dan sayangnya, ini terlihat di seluruh StackOverflow dan online dalam tutorial dan contoh.
Nonces dan infus
Menanggapi masalah yang ditemukan dengan mode ECB, kata benda juga dikenal sebagai infus dibuat. Idenya adalah bahwa kita menghasilkan variabel acak baru dan melampirkannya ke setiap enkripsi sehingga ketika Anda mengenkripsi dua pesan yang sama mereka keluar berbeda. Keindahan di balik ini adalah infus atau nonce adalah pengetahuan publik. Itu berarti penyerang dapat memiliki akses ke ini tetapi selama mereka tidak memiliki kunci Anda, mereka tidak dapat melakukan apa pun dengan pengetahuan itu.
Masalah umum yang akan saya lihat adalah bahwa orang akan menetapkan IV sebagai nilai statis seperti dalam nilai tetap yang sama dalam kode mereka. dan di sini adalah jebakan ke infus saat Anda mengulanginya Anda benar-benar kompromi seluruh keamanan enkripsi Anda.
Menghasilkan A Random IV
Catatan: SHA1 rusak tetapi saya tidak bisa menemukan cara menerapkan SHA256 ke dalam use case ini dengan benar, jadi jika ada yang ingin mengambil celah ini dan memperbaruinya akan luar biasa! Juga serangan SHA1 masih tidak konvensional karena bisa memakan waktu beberapa tahun pada sekelompok besar untuk memecahkan. Lihat detailnya di sini.
Implementasi RKPT
Padding tidak diperlukan untuk mode CTR.
Implementasi KBK
Jika Anda memilih untuk menerapkan Mode CBC melakukannya dengan PKCS7Padding sebagai berikut:
Kerentanan CBC dan CTR dan Mengapa Anda Harus Menggunakan GCM
Meskipun beberapa mode lain seperti CBC dan CTR aman, mereka mengalami masalah di mana penyerang dapat membalik data yang dienkripsi, mengubah nilainya ketika didekripsi. Jadi katakanlah Anda mengenkripsi pesan bank imajiner "Jual 100", pesan terenkripsi Anda terlihat seperti ini "eu23ng" penyerang berubah sedikit menjadi "eu53ng" dan tiba-tiba ketika mendekripsi pesan Anda, itu berbunyi "Jual 900".
Untuk menghindari hal ini, sebagian besar internet menggunakan GCM, dan setiap kali Anda melihat HTTPS, mereka mungkin menggunakan GCM. GCM menandatangani pesan terenkripsi dengan hash dan memeriksa untuk memverifikasi bahwa pesan belum diubah menggunakan tanda tangan ini.
Saya akan menghindari penerapan GCM karena kerumitannya. Anda lebih baik menggunakan perpustakaan baru Googles Tink karena di sini lagi jika Anda secara tidak sengaja mengulangi IV Anda kompromi kunci dalam kasus dengan GCM, yang merupakan kelemahan keamanan utama. Peneliti baru sedang bekerja menuju mode enkripsi tahan berulang IV di mana bahkan jika Anda mengulangi IV kuncinya tidak dalam bahaya tetapi ini belum datang arus utama.
Sekarang jika Anda ingin mengimplementasikan GCM, berikut adalah tautan ke implementasi GCM yang bagus . Namun, saya tidak dapat memastikan keamanan atau jika itu diterapkan dengan benar tetapi mendapat dasar. Perhatikan juga dengan GCM tidak ada padding.
Kunci vs. Kata Sandi
Catatan lain yang sangat penting, adalah kriptografi Kunci dan Kata Sandi bukanlah hal yang sama. Kunci dalam kriptografi perlu memiliki sejumlah entropi dan keacakan agar dianggap aman. Inilah sebabnya mengapa Anda perlu memastikan untuk menggunakan perpustakaan kriptografi yang tepat untuk menghasilkan kunci untuk Anda.
Jadi Anda benar-benar memiliki dua implementasi yang dapat Anda lakukan di sini, yang pertama adalah menggunakan kode yang ditemukan di utas StackOverflow ini untuk Pembuatan Kunci Acak . Solusi ini menggunakan penghasil angka acak yang aman untuk membuat kunci dari awal yang dapat Anda gunakan.
Opsi lain yang kurang aman adalah menggunakan input pengguna seperti kata sandi. Masalah yang kita bahas adalah bahwa kata sandi tidak memiliki cukup entropi, jadi kita harus menggunakan PBKDF2 , sebuah algoritma yang mengambil kata sandi dan memperkuatnya. Berikut ini adalah implementasi StackOverflow yang saya sukai . Namun pustaka Google Tink memiliki semua ini bawaan dan Anda harus memanfaatkannya.
Pengembang Android
Satu poin penting untuk ditunjukkan di sini adalah tahu bahwa kode android Anda adalah rekayasa balik dan kebanyakan kasus kebanyakan kode java juga. Itu berarti jika Anda menyimpan kata sandi dalam teks biasa dalam kode Anda. Seorang hacker dapat dengan mudah mengambilnya. Biasanya, untuk jenis enkripsi ini, Anda ingin menggunakan Asymmetric Cryptography dan sebagainya. Ini di luar cakupan posting ini jadi saya akan menghindari menyelam ke dalamnya.
Sebuah bacaan yang menarik dari 2013 : hai bahwa 88% dari implementasi Crypto di Android yang dilakukan tidak benar.
Pikiran terakhir
Sekali lagi saya akan menyarankan menghindari menerapkan perpustakaan java untuk crypto secara langsung dan menggunakan Google Tink , ini akan menghemat sakit kepala karena mereka telah benar-benar melakukan pekerjaan yang baik dalam mengimplementasikan semua algoritma dengan benar. Dan bahkan kemudian pastikan Anda memeriksa masalah yang muncul di Tink github, kerentanan muncul di sana-sini.
Jika Anda memiliki pertanyaan atau umpan balik, jangan ragu untuk berkomentar! Keamanan selalu berubah dan Anda harus melakukan yang terbaik untuk mengatasinya :)
sumber
getInstanceStrong()
metodeCipher
lebih disukai daripada SHA1PRNGSaya akan merekomendasikan untuk menggunakan beberapa cypher simetris standar yang banyak tersedia seperti DES , 3DES atau AES . Meskipun itu bukan algoritma yang paling aman, ada banyak implementasi dan Anda hanya perlu memberikan kunci kepada siapa saja yang seharusnya mendekripsi informasi dalam barcode. javax.crypto.Cipher adalah apa yang ingin Anda kerjakan di sini.
Mari kita asumsikan byte yang akan dienkripsi berada
Selanjutnya, Anda akan memerlukan byte kunci dan inisialisasi vektor
Sekarang Anda dapat menginisialisasi Cipher untuk algoritma yang Anda pilih:
Enkripsi akan seperti ini:
Dan dekripsi seperti ini:
sumber
DESede
algoritma? Karena ini adalah pertanyaan populer (dan jawaban), akan memalukan untuk mendorong orang untuk menggunakan DES, karena sandi sangat lemah menurut standar saat ini.Saya menggunakan Sun's Base64Encoder / Decoder yang dapat ditemukan di Sun's JRE, untuk menghindari JAR lain di lib. Itu berbahaya dari titik menggunakan OpenJDK atau JRE orang lain. Selain itu, apakah ada alasan lain saya harus mempertimbangkan untuk menggunakan Apache commons lib dengan Encoder / Decoder?
sumber
Terima kasih ive membuat kelas ini menggunakan kode Anda, mungkin seseorang menemukannya userfull
objek crypter
sumber
Pembaruan pada 12-DEC-2019
Tidak seperti beberapa mode lain seperti CBC, mode GCM tidak mengharuskan IV tidak dapat diprediksi. Satu-satunya persyaratan adalah bahwa IV harus unik untuk setiap doa dengan kunci yang diberikan. Jika diulangi sekali untuk kunci yang diberikan, keamanan dapat dikompromikan. Cara mudah untuk mencapai ini adalah dengan menggunakan IV acak dari generator nomor acak pseudo yang kuat seperti yang ditunjukkan di bawah ini.
Menggunakan urutan atau stempel waktu sebagai IV juga dimungkinkan, tetapi mungkin tidak sepele kedengarannya. Misalnya, jika sistem tidak melacak dengan benar urutan yang sudah digunakan sebagai IV di toko persisten, doa dapat mengulangi IV setelah sistem reboot. Demikian juga, tidak ada jam yang sempurna. Jam komputer menyesuaikan kembali dll.
Selain itu, kunci harus diputar setelah setiap doa 2 ^ 32. Untuk perincian lebih lanjut tentang persyaratan IV, lihat jawaban ini dan rekomendasi NIST .
Ini adalah kode enkripsi & dekripsi yang baru saja saya tulis di Java 8 dengan mempertimbangkan poin-poin berikut. Semoga seseorang akan menemukan ini berguna:
Algoritma Enkripsi : Blok cipher AES dengan kunci 256 bit dianggap cukup aman. Untuk mengenkripsi pesan lengkap, mode perlu dipilih. Enkripsi yang diautentikasi (yang memberikan kerahasiaan dan integritas) direkomendasikan. GCM, CCM dan EAX adalah mode enkripsi terotentikasi yang paling umum digunakan. GCM biasanya lebih disukai dan berkinerja baik di arsitektur Intel yang memberikan instruksi khusus untuk GCM. Ketiga mode ini adalah mode berbasis CTR (berbasis counter) dan oleh karena itu mereka tidak perlu padding. Akibatnya mereka tidak rentan terhadap serangan terkait padding
Inisialisasi Vektor (IV) diperlukan untuk GCM. IV bukan rahasia. Satu-satunya persyaratan adalah harus acak atau tidak dapat diprediksi. Di Jawa,
SecuredRandom
kelas ini dimaksudkan untuk menghasilkan angka acak semu yang kuat secara kriptografis. Algoritma bilangan pseudo-acak dapat ditentukan dalamgetInstance()
metode ini. Namun, sejak Java 8, cara yang disarankan adalah menggunakangetInstanceStrong()
metode yang akan menggunakan algoritma terkuat yang dikonfigurasi dan disediakan olehProvider
NIST merekomendasikan 96 bit IV untuk GCM untuk mempromosikan interoperabilitas, efisiensi, dan kesederhanaan desain
Untuk memastikan keamanan tambahan, dalam implementasi berikut
SecureRandom
diunggulkan kembali setelah menghasilkan setiap 2 ^ 16 byte generasi byte pseudo acakPenerima perlu mengetahui IV untuk dapat mendekripsi teks sandi. Oleh karena itu IV harus ditransfer bersama dengan teks sandi. Beberapa implementasi mengirim IV sebagai AD (Data Terkait) yang berarti bahwa tag otentikasi akan dihitung pada teks sandi dan IV. Namun, itu tidak diperlukan. IV dapat dengan mudah ditunda dengan teks sandi karena jika IV diubah selama transmisi karena serangan yang disengaja atau kesalahan sistem jaringan / file, validasi tag otentikasi akan tetap gagal
String tidak boleh digunakan untuk menyimpan pesan teks atau kunci yang jelas karena String tidak dapat diubah dan dengan demikian kita tidak dapat menghapusnya setelah digunakan. String tidak jelas ini kemudian berlama-lama di memori dan dapat muncul di tumpukan sampah. Untuk alasan yang sama, klien yang memanggil metode enkripsi atau dekripsi ini harus menghapus semua variabel atau array yang menyimpan pesan atau kunci setelah mereka tidak lagi diperlukan.
Tidak ada penyedia yang dikodekan dalam kode mengikuti rekomendasi umum
Akhirnya untuk transmisi melalui jaringan atau penyimpanan, kunci atau teks sandi harus dikodekan menggunakan pengkodean Base64. Detail Base64 dapat ditemukan di sini . Pendekatan Java 8 harus diikuti
Array byte dapat dihapus menggunakan:
Namun, pada Java 8, tidak ada cara mudah untuk menghapus
SecretKeyspec
danSecretKey
karena implementasi dari dua antarmuka ini tampaknya tidak menerapkan metodedestroy()
antarmukaDestroyable
. Dalam kode berikut, metode terpisah ditulis untuk menghapusSecretKeySpec
danSecretKey
menggunakan refleksi.Kunci harus dihasilkan menggunakan salah satu dari dua pendekatan yang disebutkan di bawah ini.
Perhatikan bahwa kunci adalah rahasia seperti kata sandi, tetapi tidak seperti kata sandi yang dimaksudkan untuk penggunaan manusia, kunci dimaksudkan untuk digunakan oleh algoritma kriptografi dan karenanya harus dibuat hanya dengan menggunakan cara di atas.
Kunci enkripsi dapat dihasilkan terutama dalam dua cara:
Tanpa kata sandi apa pun
Dengan kata sandi
Pembaruan Berdasarkan Komentar
Seperti yang ditunjukkan oleh @ MaartenBodewes, jawaban saya tidak menangani apa pun
String
seperti yang diminta oleh pertanyaan. Oleh karena itu, saya akan berusaha mengisi celah itu untuk berjaga-jaga seandainya seseorang menemukan jawaban ini dan bertanya-tanya tentang penanganannyaString
.Seperti yang ditunjukkan sebelumnya dalam jawaban, penanganan informasi sensitif di a
String
, secara umum, bukan ide yang baik karenaString
tidak dapat diubah dan dengan demikian kami tidak dapat menghapusnya setelah digunakan. Dan seperti yang kita tahu, bahkan ketika aString
tidak memiliki referensi yang kuat, pengumpul sampah tidak segera bergegas untuk mengeluarkannya dari tumpukan. Dengan demikian,String
terus ada di dalam memori untuk jendela waktu yang tidak diketahui meskipun tidak dapat diakses oleh program. Masalahnya adalah, tumpukan tumpukan selama jangka waktu itu akan mengungkapkan informasi sensitif. Oleh karena itu, selalu lebih baik untuk menangani semua informasi sensitif dalam array byte atau array char dan kemudian mengisi array dengan 0s begitu tujuannya dilayani.Namun, dengan semua pengetahuan itu, jika kita masih berakhir dalam situasi di mana informasi sensitif yang akan dienkripsi berada dalam a
String
, pertama-tama kita perlu mengubahnya menjadi array byte dan menjalankanencrypt
dandecrypt
fungsi yang diperkenalkan di atas. (Kunci input lainnya dapat dibuat menggunakan potongan kode yang disediakan di atas).A
String
dapat dikonversi menjadi byte dengan cara berikut:Pada Java 8,
String
disimpan secara internal di heap denganUTF-16
encoding. Namun, kami telah menggunakan diUTF-8
sini karena biasanya memakan waktu lebih sedikit daripadaUTF-16
, terutama untuk karakter ASCII.Demikian juga, array byte terenkripsi juga dapat dikonversi menjadi String seperti di bawah ini:
sumber
String
menggunakan fungsi yang dibuat di atas akan sepele. Namun, pada pandangan kedua setelah membaca komentar Anda, saya mengerti bahwa itu mungkin tidak jelas. Saya pasti akan mengedit untuk menambahkan detail itu.Bagaimana dengan ini:
Bekerja dengan baik untuk saya dan agak kompak.
sumber
input.length <= secret.length
memegang dan tidaksecret
pernah digunakan kembali ini aman dan disebut aone-time-pad
. Dalam kasusinput.length > secret.length
ini adalah varian dari cipher Vigenère dan dianggap sangat lemah.Anda bisa menggunakan Jasypt
Dengan Jasypt, mengenkripsi dan memeriksa kata sandi bisa sesederhana ...
Enkripsi:
Dekripsi:
Gradle:
Fitur:
sumber
Jasypt
disediakan? Saya tidak bisa mengetahuinya dari situs web mereka. Apakah tidak bisa dibedakan dengan serangan plaintext yang dipilih? Integritas? Kerahasiaan?Inilah implementasi saya dari meta64.com sebagai Spring Singleton. Jika Anda ingin membuat instance ciper untuk setiap panggilan yang juga berfungsi, dan kemudian Anda bisa menghapus panggilan 'disinkronkan', tetapi waspadalah 'cipher' tidak aman untuk thread.
sumber
Berikut solusi sederhana dengan hanya
java.*
danjavax.crypto.*
dependensi untuk enkripsi byte menyediakan kerahasiaan dan integritas . Itu harus dibedakan di bawah serangan plaintext yang dipilih untuk pesan pendek dalam urutan kilobyte.Ini digunakan
AES
dalamGCM
mode tanpa padding, kunci 128bit diturunkanPBKDF2
dengan banyak iterasi dan garam statis dari kata sandi yang disediakan. Ini memastikan brute forcing passwords sulit dan mendistribusikan entropi ke seluruh kunci.Vektor inisialisasi acak (IV) dihasilkan dan akan ditambahkan ke ciphertext. Selanjutnya, byte statis
0x01
didahului dengan byte pertama sebagai 'versi'.Seluruh pesan masuk ke kode otentikasi pesan (MAC) yang dihasilkan oleh
AES/GCM
.Ini dia, nol enkripsi kelas dependensi eksternal memberikan kerahasiaan dan integritas :
Di sini seluruh proyek dengan CLI yang bagus: https://github.com/trichner/tcrypt
Edit: sekarang dengan yang sesuai
encryptString
dandecryptString
sumber
encryptString
dandecryptString
:)Saya akan mempertimbangkan untuk menggunakan sesuatu seperti https://www.bouncycastle.org/ Ini adalah perpustakaan prebuilt yang memungkinkan Anda untuk mengenkripsi apa pun yang Anda suka dengan sejumlah Ciphers yang berbeda. Saya mengerti bahwa Anda hanya ingin melindungi dari pengintaian, tetapi jika Anda benar-benar ingin melindungi informasi, menggunakan Base64 tidak akan benar-benar melindungi Anda.
sumber
Berikut adalah beberapa tautan yang dapat Anda baca yang didukung Java
Mengenkripsi / mendekripsi aliran data.
JCERefGuide
Contoh Enkripsi Java
sumber
Seperti yang sudah diceritakan oleh banyak orang, Anda harus menggunakan kode standar yang terlalu banyak digunakan seperti DES atau AES.
Contoh sederhana tentang bagaimana Anda dapat mengenkripsi dan mendekripsi string dalam java menggunakan AES .
sumber
Berikut ini adalah solusi salin / tempel. Saya juga merekomendasikan membaca dan memilih jawaban @ Konstantino meskipun tidak menyediakan kode apa pun. Vektor inisialisasi (IV) seperti garam - tidak harus dirahasiakan. Saya baru mengenal GCM dan tampaknya AAD adalah opsional dan hanya digunakan dalam keadaan tertentu. Atur kunci dalam variabel lingkungan
SECRET_KEY_BASE
. Gunakan sesuatu seperti KeePass untuk menghasilkan kata sandi 32 karakter. Solusi ini dimodelkan setelah solusi Ruby saya.Berikut ini sebuah contoh:
sumber
Anda mungkin ingin mempertimbangkan beberapa alat otomatis untuk melakukan pembuatan kode enkripsi / dekripsi misalnya. https://www.stringencrypt.com/java-encryption/
Ini dapat menghasilkan kode enkripsi dan dekripsi yang berbeda setiap kali untuk string atau enkripsi file.
Ini cukup praktis ketika menyangkut enkripsi string cepat tanpa menggunakan RSA, AES dll.
Hasil sampel:
Kami menggunakannya sepanjang waktu di perusahaan kami.
sumber
sumber
sumber