Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Security
Code

Membuat Tanda Tangan Digital dengan Swift

by
Difficulty:IntermediateLength:LongLanguages:

Indonesian (Bahasa Indonesia) translation by Husain Ali Yahya (you can also view the original English article)

Tujuan utama dari sebuah tanda tangan digital adalah untuk memverifikasi integritas dari beberapa informasi. Contoh sederhananya, anggap kamu memiliki sebuah berkas yang ditransfer melalui jaringannya dan kamu ingin mengecek apakah keseluruhan berkasnya ditransfer dengan benar. Dalam kasus tersebut, kamu bisa menggunakan sebuah checksum.

"Checksum adalah datum berukuran kecil yang didapat dari sebuah blok data digital untuk tujuan pengecekkan error yang mungkin muncul selama transmisi atau penyimpanannya" - Wikipedia

Bagaimana cara kita mendapatkan checksum tersebut? Pilihan terbaiknya adalah dengan menggunakan hash. Sebuah hash function akan mengambil sebuah sejumlah variabel data dan akan mengeluarkan sebuah tanda tangan dengan panjang tetap. Contohnya, kita bisa mempublikasikan sebuah berkas bersama dengan hash-nya secara online. Ketika seseorang mengunduh berkasnya, mereka bisa menjalankan hash funtion yang sama pada versi berkas mereka sendiri dan membandingkan hasilnya. Jika hash-hash nya sama makan berkas yang disalin atau diunduh sama dengan yang asli.

Hash juga merupakan sebuah one-way function. Dengan hasil output-nya, tidak ada cara komputasional yang mungkin untuk mengembalikkan hash sehingga input aslinya terungkap. SHA, Secure Hash Algorithm, adalah sebuah standar yang terkenal yang mengacu ke sekumpulan hash function yang memiliki properti ini dan beberapa properti lainnya yang membuat mereka berguna dalam tanda tangan digital.

Mengenai SHA

SHA telah mengalami banyak iterasi semenjak ia pertama kali dipublikasikan. Iterasi pertama dan kedua-nya, SHA-0 dan SHA-1, sekarang diketahu memiliki banyak kelemahan besar. Mereka tidak lagi diterima untuk impelementasi keamanan: mereka pada umumnya tidak boleh digunakan untuk aplikasi yang bergantung pada keamanan. Namun, keluarga SHA-2 memiliki versi yang disebut SHA-256 dan SHA-512, dan mereka dianggap aman. "256" dan "512" mengacu ke angka bit yang dihasilkan. Untuk panduan ini, kita akan menggunakan SHA-512.

Catatan: algoritma hash populer lainnya adalah MD5. Dia juga memiliki beberapa kecacatan signifikan.

Penggunaan SHA bagus untuk mengecek apakah data-nya korup secara tidak sengaja, tapi ini tidak mencegah pengguna berbahaya untuk mengganggu datanya. Dengan keluaran hash pada ukuran yang tetap, segala yang penyerang harus lakukan adalah mencari tahu algoritma yang digunakan untuk menghasilkan outputnya, mengubah data-nya, dan mengomputasi ulang hash-nya. Apa yang kita butuhkan adalah beberapa informasi rahasia yang ditambahkan ke mix-nya ketika meng-hash data-nya sehingga penyerang tidak bisa mengomputasi ulang hash-nya tanpa mengetahui rahasianya. Ini disebut dengan Hash Message Authentication Code (HMAC).

HMAC

HMAC bisa mengotentikasi pecahan informasi atau pesan untuk memastikan bahwa itu berasal dari pengirim yang tepat dan informasinya belum diubah. Sebuah skenaio yang umum adalah saat kamu berbicara dengan sebuah sercer dengan back-end API untuk aplikasimu. Ini bisa jadi penting untuk mengotentikasi untuk memastikan bahwa hanya aplikasimu yang diizinkan untuk berbicara dengan API-nya. API-nya akan memiliki access control ke sumberdaya tertentu, seperti endpoint /register_user. Kliennya perlu sign (mendaftarkan) permintaannya ke endpoint /register_user agar bisa menggunakannya.

Ketika mendaftarkan sebuah permintaan, adalah hal yang umum untuk mengambil bagian permintaan yang terpilih, seperti parameter POST dan URL-nya, dan menggabungkan mereka menjadi sebuah string. Menyepakati elemen-elemen tersebut dan meletakkan mereka dalam suatu urutan tertentu disebut dengan canonicalization. Dalam HMAC, string yang digabungkan akan ter-hash bersama dengan secret key untuk memproduksi signature-nya. Ketimbang memanggil mereka hash, kita menggunakan istilah signature (tanda tangan) dengan cara yang sama sebuah tanda tangan orang asli digunakan dalam kehidupan nyata untuk mengidentifikasi identitas atau integritas. Tanda tangannya ditambahkan ke permintaan klien sebagai sebuah request header (biasanya disebut "Signature" juga). Sebuah signature kadang disebut message digest, dan kedua istilah itu bisa digunakan silih-berganti.

Di sisi API, server-nya mengulangi proses penggabungan string dan membuat sebuah signature. Jika signature-nya cocok, dia membuktikan bahwa aplikasinya harus memiliki kode rahasia-nya. Ini membuktikan identitas dari aplikasinya. Semenjak parameter spesifik dari permintaannya juga merupakan bagian dari string-nya untuk ditanda tangani, dia juga menjamin integritas dari permintaannya. Dia mencegah penyerang dari melakukan penyerangan di tengah-tengah, contohnya, dan mengubah parameter permintaannya ke yang mereka suka.

Pada kode ini, function CCHmac mengambil sebuah parameter untuk tipe dari hash function untuk digunakan, bersama dengan dua string byte dan panjang mereka - pesannya dan sebuah secret key. Untuk keamanan, gunakan setidaknya sebuah kunci 256-bit (32 byte) yang dihasilkan dari sebuah cyptograhically secure random number generator. Untuk memverikasi bahwa semuanyab berjalan dengan baik di sisi lain, jalankan contohnya lalu masukkan secret key dan pesan pada server remote ini dan verifikasi bahwa output-nya sama.

Kamu juga bisa menambah sebuah timestamp header ke permintaannya dan menambahkan string untuk membuat permintaannya lebih unik. Ini bisa membuat API menyortir serangan balik. Contohnya, API bisa menghentikan permintaan jika timestamp-nya telah lebih dari 10 menit.

Walaupun menggunakan versi SHA yang aman adalah hal yang bagus, ternyata banyak kerentanan dari versi SHA yang tidak aman tidak berlaku di HMAC. Untuk alasan ini, kamu bisa melihat SHA1 digunakan dalam produksi kode. Namun, dari sudut pandang hubungan masyarakat, ini bisa jadi buruk jika kamu harus menjelaskan alasannya, berbicara secara kriptografi, cukup bagus untuk menggunakan SHA1 dalam konteks ini. Banyak kelemahan dari SHA1 dikarenakan apa yang disebut dengan collision attacks. Pengaudit kode atau ilmuwan keamanan berharap kode-mu tahan collision tanpa mempedulikan konteksnya. Dan juga, jika kamu menulis kode modular di mana kamu bisa menukar signing function-nya dengan yang lain nanti, kamu bisa melupakan untuk memperbaharui hash function yang tidak amannya. Jadi, kita akan tetap menggunakan SHA-512 sebagai algoritma pilihan kita.

Operasi HMAC CPU cepat, tapi satu kekurangannya adalah masalah key exchange. Bagaimana kita membiarkan satu sama lain mengetahui secret key-nya tanpa dicegat. Contohnya, kamu mungkin perlu API untuk secara dinamis menambah atau menghapus aneka aplikasi atau platform dari sebuah daftar putih. Dalam skenario ini, aplikasi-aplikasi akan perlu didaftarkan ke aplikasi-nya di tiap pendaftaran yang berhasil. Kamu bisa mengirim key-nya melalui HTTPS dan menggunakan SSL pinning, tapi tetap saja selalu ada kekhawatiran kalau nanti key-nya dicuri selama proses pertukaran Solusi dari masalah key exchange adalah dengan membuat sebuah key yang tidak meninggalkan perangkatnya terlebih dahulu. Ini bisa dicapai menggunakan Public Key Cryptography, dan sebuah standar yang sangat populer dan diterima yaitu RSA.

RSA

RSA adalah singkatan dari Rivest-Shamir-Adleman (Pencipta dari cryptosystem-nya). Dia melingkupi pengambilan keuntungan dari kesulitan pemfaktoran produknya dari dua angka prima yang sangat besar. RSA bisa digunakan untuk enkripsi dan otentikasi, meskipun untuk contoh ini kita hanya akan menggunakannya untuk otentikasi. RSA menghasilkan dua keys, satu public dan satu private, yang bisa didapat dengan function SecKeyGeneratePair. Saat digunakan untuk otentikasi, private key digunakan untuk membuat tanda tangannya, sementara public key memverifikasi tanda tangannya. Adalah hal yang tidak mungkin secara komputasional untuk mendapatkan private key dari sebuah public key.

Contoh berikutnya mendemonstrasikan apa yang Apple dan perusahaan konsol gaming populer lainnya gunakan ketika mendistribusikan software-nya. Katakan saja perusahaanmu membuat dan mengantarkan sebuah berkas secara periodik yang penggunanya akan seret ke bagian file sharing dari aplikasimu di iTunes. Kamu ingin memastikan berkas-berkas yang kamu kirim tidak pernah dicegat sebelum diurai dalam aplikasinya. Perusahaanmu akan menahan dan melindungi private key yang digunakan untuk menandatangani berkasnya. Dalam bundel aplikasinya terdapat sebuah salinan dari public key yang digunakan untuk memverifikasi berkasnya. Dengan private key yang tidak pernah dikirim atau dimasukkan ke dalam aplikasinya, maka tidak ada cara untuk pengguna berbahaya untuk bisa masuk dengan versi aplikasi mereka sendiri (selain menerobos perusahaannya dan mencuri private ley-nya).

Kita akan menggunakan SecKeyRawSign untuk menandatangani berkasnya. Akan cukup lambat untuk menandatangani keseluruhan konten menggunakan RSA, jadi hash dari berkas-nya lah yang ditanda tangani Di samping itu, data yang dilewatkan ke RSA juga harus di-hash sebelum penandatanganan karena beberapa kelemahan sekuriti.

Pada kode ini, kita menggunakan function CC_SHA512 untuk menspesifikasikan SHA-512 nya lagi. (RSA, tidak seperti HMAC, jadi tidak aman jika hash function yang mendasarinya tidak aman.) Kita juga akan menggunakan 4096 sebagai ukuran key-nya yang akan diatur oleh parameter kSecAttrKeySizeInBits. 2048 adalah ukuran minimum yang direkomendasikan. Ini untuk mencegah sebuah sistem jaringan komputer yang bertenaga meretakkan RSA key-nya (meretakkan di sini berarti memfaktorkan RSA key-nya dikenal juga dengan faktorisasi dari sebuah modulus public). Grup RSA telah mengestimasi bahwa 2048-bit key bisa diretakkan beberapa saat sebelum tahun 2030. Jika kamu ingin datamu aman pada saat setelah itu, akan jadi hal yang bagus untuk mengatur angka yang lebih tinggi seperti 4096.

Key yang dihasilkan adalah dalam bentuk objek SecKey. Sebuah masalah dari implementasi Apple dari SecKey adalah dia tidak melingkupi semua informasi penting yang membuat sebuah public key, jadi dia bukanlah sebuah sertifikat DER-encoded X.509 yang valid. Menambhakan informasi yang hilang ke formatnya untuk aplikasi iOS atau OS X, bahkan platform server-side seperti PHP, akan memerlukan banyak pekerjaan dan melingkupi pekerjaan dalam sebuah format yang dikenal dengan ASN.1. Untungnya, ini telah diperbaiki di iOS 10 dengan function SecKey baru untuk menghasilkan, mengekspor, dan mengimpor key.

Kode berikut menunjukkanmu sisi lain dari komunikasi - class yang menerima sebuah public key melalui SecKeyCreateWithData untuk memverifikasi berkas menggunakan function SecKeyRawVerifiy.

Kamu bisa mencoba ini dan memverifikasi bahwa itubekerja menggunakan sebuah tes sederhana seperti berikut:

Ada satu kelemahan dari RSA — pembuatan key nya lambat! Waktu untuk pembuatan key-nya bergantung pada ukuran key tersebut. Pada perangkat baru sebuah kunci 4096 bit hanya akan memakan beberapa detik, tapi jika kamu menjalankannya pada iPod Touch 4th generation, akan memakan satu menit. Ini tak masalah jika kamu hanya membuat keys beberapa kali dalam sebuah ko,puter, tapi bagaimana jika kita harus membuat key berkali-kali pada sebuah ponsel? Kita tidak bisa menurunkan ukuran key-nya karena akan mengurangi keamanannya.

Jadi apa solusinya? Ya, Elliptic Curve Cryptography (ECC) adalah sebuah pendekatan yang sedang naik daun. Seperangkat algoritma yang berdasarkan kurva elipsis di atas bidang yang terbatas. Kunci ECC jauh lebih kecil ukurannya dan lebih cepat untuk dibuat ketimbang RSA. Sebuah key 256-bits saja sudah memiliki tingkat keamanan yang sangat tinggi! Untuk mengambil keuntungan dari ECC, kita tidak perlu banyak mengganti kodenya. Kita bisa mendaftarkan data kita menggunakan function SecKeyRawSign yang sama lalu mengatur parameter-nya agar menggunakan Elliptic Curve Digital Signature Algorithm (ECDSA)

Tip: Untuk lebih banyak ide mengenai implementasi RSA, kamu bisa mengecek pustaka pembantu SwiftyRSA yang berfokus pada enkripsi dan juga penandatanganan pesan.

ECDSA

Bayangkan skenario berikut: sebuah aplikasi chat mengizinkan penggunanya untuk mengirimkan pesan pribadi ke satu sama lain, tapi kamu ingin memastikan seorang musuh tidak mengganti pesannya dalam perjalanannya ke pengguna lainnya. Mari lihat cara kamu bisa mengamankan komunikasi mereka dengan kriptografi.

Pertama, tiap pengguna membuat sebuah public dan private keypair di ponsel mereka. Private keys mereka disimpan dalam memori dan tidak akan pernah meninggalkan perangkat, sementara public keys dikirim ke satu sama lainnya. Seperti sebelumnya, private key digunakan untuk menandatangani data yang dikirim. Sementara public key digunakan untuk memverifikasi. Jika seorang penyerang berusaha mengambil public key selama pengiriman, segala yang bisa dilakukan adalah memverifikasi integritas dari pesan asli dari pengirimnya. Seorang penyerang tidak bisa mengubah sebuah pesan karena mereka tidak memiliki private key yang dibutuhkan untuk merekonstruksi tanda tangannya.

Ini adalah salah satu keuntungan lain dari penggunaan ECDSA di iOS. Kita bisa menggunakan fakta bahwa saat ini elliptic curve keys adalah satu-satunya yang bisa disimpan di kantong aman perangkatnya. Semua keys lainnya disimpan dalam sebuah keychain yang mengenkripsi item-item nya ke area penyimpanan bawaan perangkatnya. Pada perangkat yang memilikinya, area keamanannya terpisah dari prosesornya, dan penyimpan key diterapkan di perangkat keras tanpa akses langsung perangkat lunak. Area keamanannya bisa menyimpan sebuah private key dan mengoperasikannya untuk menghasilkan output yang dikirim ke aplikasimu tanpa mengekspos private key yang sebenarnya dengan memuatnya ke memori!

Saya akan menambahkan dukungan untuk pembuatan ECDSA private key pada area keamanan dengan menambahkan opsi kSecAttrTokenIDSecureEnclave ke parameter kSecAttrTokenID. Kita bisa memulai contoh ini dengan sebuah objek User yang akan menghasilkan sebuah keypair saat inisialisasi.

Selanjutnya, kita akan membuat beberapa helper dan contoh functions. Sebagai contoh, class-nya akan mengizinkan seorang pengguna untuk menginisiasi sebuah ercakapan dan mengirim sebuah pesan. Tentu saja, dalam aplikasimu, kamu akan mengonfigurasi ini untuk memasukkan pengaturan jaringan spesifikmu.

Selanjutnya, kita akan melakukan penandatangan dan verifikasi yang sebenarnya. ECDSA, tidak seperti RSA, tidak perlu di-hash sebelum penandatanganan. Namun, jika kamu ingin memiliki sebuah function di mana algoritmanya bisa dengan mudah diganti tanpau harus melakukan banyak perubahan, maka tidak akan ada masalah sama sekali jika tetap meng-hash data-nya sebelum penandatanganan.

Ini memverifikasi pesannya, sekaligus "mengidentifikasi" pengguna tertentu semenjak hanya pengguna tersebut yang memiliki private key-nya.

Ini tidak berarti kita menghubungkan key-nya dengan pengguna-nya di dunia nyata —masalah mencocokkan sebuah public key ke pengguna tertentu adalah masalah di wilayah yang lain. Sementara solusinya berada di luar lingkup panduan ini, aplikasi chat aman yang populer seperti Signal dan Telegram mengizinkan penggunanya untuk memverifikasi sidik jari atau nomor melalui saluran komunikasi sekunder. Mirip dengan Pidgin yang menawarkan skema tanya jawab di mana kamu menanyakan pertanyaan yang hanya pengguna tersebut yang bisa tahu. Solusi ini membuka sebuah dunia perdebatan baru mengenai pendekatan terbaik yang harus dipakai.

Namun, solusi kriptografik kita tidak memverifikasi bahwa pesannya hanya bisa dikirim oleh seseorang yang memiliki private key tertentu.

Mari jalankan sebuah tes sederhana dari contoh kita:

OAuth dan SSO

Sering kali saat berurusan dengan layanan pihak ketiga, kamu akan melihat istilah tingkat tinggi lainnya yang digunakan untuk otentikasi seperti OAuth dan SSO. Sementara tutorial ini mengenai pembuatan sebuah signature, saya akan menjelaskan secara singkat maksud dari istilah tersebut.

OAuth adalah sebuah protokol untuk otentikasi dan otorisasi. Dia bekerja sebagai sebuah penengah antara akun seseorang dan layanan pihak ketiga dan bertujuan untuk menyelesaikan masalah penyeleksian akses otorisasi ke data-mu. Jika kmau masuk ke layanan X melalui Facebook, sebuah layar akan memberimu pertanyaan, contohnya, apakah layanan X diizinkan untuk mengakses foto Facebook-mu atau tidak. Itu dicapai dengan menyediakan sebuah token tanpa mengungkapkan password pengguna.

Single sign-on, atau SSO, menjelaskan alur di mana sebuah pengguna terotentikasi bisa menggunakan krendensial login yang sama untuk mengakses aneka layanan. Sebuah contoh dari ini adalah cara akun Gmail bisa digunakan untuk masuk ke Youtube. Jika kamu memiliki beberapa layanan berbeda di perusahaanmu, kamu tidak akan ingin membuat beberapa akun terpisah untuk tiap layanan tersebut.

Kesimpulan

Pada panduan ini, kamu telah melihat cara membuat signatures menggunakan standar yang paling populer. Sekarang kamu telah mengetahu konsep utama-nya, mari kita rekap!

  • Gunakan HMAC saat kamu butuh kecepatan dan yakin secret key-nya bisa dipertukarkan dengan aman.
  • Jika key-nya harus melewati sebuah jaringan, lebih baik menggunakan RSA atau ECDSA.
  • RSA masih standar yang paling populer. Langkah verifikasinya cukup cepat. Gunakan RSA jika tim-mu sudah familiar dengan standar-nya.
  • Jika kamu harus secara terus menerus membuat key pada perangkat yang lambat, gunakan ECDSA. Walaupun verifikasi ECDSA lebih lambar dari verifikasi RSA, itu tidak sebanding dengan banyaknya waktu yang tersimpan dari pembuatan key dengan RSA.

Jadi itulah digital signatures di Swift. Jika kamu memiliki pertanyaan, jangan ragu untuk menuliskannya di kolom komentar, dan selagi senggang. Cek lah beberapa panduan keren lainnya mengenai keamanan data dan pengembangan aplikasi di Swift!


Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.