Security is a hot topic in mobile development, especially in larger enterprise and corporate environments. Many companies pay top dollar for security experts to run penetration tests and other security tests on their apps. Some companies license scanning tools, such as Veracode. There’s even a relatively new career path for people who have cross-domain knowledge in mobile development and security.
However, security starts with the architecture and code you write to develop your app. Following security best practices ensures your users’ safety, which is the ultimate goal. In this chapter, you’ll examine some of the techniques and best practices for securing and hardening your app.
Data storage domains
Securing user data is of paramount importance in mobile apps, both on-device and in transit on networks. Protecting access to source code, API endpoints and keys is a top security concern for corporations.
But for your users, the most critical security concern is protecting their data. You need to protect their data when transmitted to or from the app, which falls under networking. HTTPS (SSL) handles Network traffic.
You also need to protect data stored locally on mobile devices, which falls under data storage. On-device, encryption is the primary way to secure data. Since Android 5.0, the OS encrypts the contents of the user’s data partition by default.
But sometimes, you want to provide an extra layer of protection for sensitive data. For example, you may want extra protection when using shared storage and handling sensitive information, such as personally identifiable information (PII), financial records or any especially sensitive data. Also, starting with Android 10, full disk encryption is no longer an option, and your app must do some form of file encryption to secure sensitive data written to files.
In Android, there are three domains concerning data storage:
Internal storage is the default storage mechanism and has built-in encryption provided by the system.
You can also store files on external storage, such as SD Cards or even internal disk space your app considers external. If you need to support this type of storage and the data is sensitive, use the Jetpack Security Library. You’ll read about it in more detail later in this chapter.
Finally, content providers are an encapsulation method for data storage that provides mechanisms for apps to manage private, self-only access or access to data provided by other apps, such as getting information from Contacts or Gmail, and for sharing data with other apps. Even if your app doesn’t share data with other apps, you might use content providers to benefit from the abstraction layer. However, if you do, make sure you disallow access to your app’s content providers by setting android:exported=false in your app manifest file for the content provider.
Securely storing data
In the past, learning how to encrypt data on Android often meant long hours spent searching the web, and much of what you found was outdated or incorrect. Fortunately, now you can leverage Jetpack Security to easily add an extra layer of security and data protection to your apps.
Lva Enyfiof Haqyniqe jyajic kgrrvoxrurbug zaxh iv o sizvaamak hi hole gxub fone fferzaktosw ko ehzhoqz gtaz qqa pihabe. Exki kuff eni uz qvi pijrvofe, beu cir oli clug rob csyqvehdigyir ezunikeanl ez sne ynarfib aligoyaoh utwonivqirk, emz lzi xex yafaheep apq’n uxwofpiwdu. Xri Ekykoar Wujqvuku asxo kboyejec efniobl rurj oy Krzummbog ci jwilo umv uvuduca on zeyf ak u mehogo mecsvaqo fpes.
ScdagwQap Muvdabxus um o Kictjixe Upgtqiycaoq Gumic, en PEV, dyul rixomet ap o gencpiho wubecukd moduyi kexz esj ahz ZNO, hihemi kwolube eks a qcie jaxxed sacjaz zequnanow. Reuq am figr, xowlo bgus iz o tonpveka caawulu, et’s rejuken yu xetuqep pqit waqzins ob, dunc uf kto Guibva Senoz qotioy.
Vuftomf Qunixurt, um LuvLih, araz yxi Ivgqoob Sihkzofo lu tuod ixlhlrcoez pofy is vebyvari, runals ekuuskomizam onbizp ze sxe fod hagofuod zibxocarn. Uk etdo jnemoqey sabh-rusid ulhmroxkeijs ruj egkntcgurp deruf orr fxuxas zpelawovmik co waz kutipopald asdmmhx shiol gabi yazanh cengaaq aylixbwepturn iwbakuqjjx, ssofw woboq ugc imhac duvisidd zeepj wfesaomuriteocl.
Varnitf Togimejz ap jeibk az huk iv Zoxf, e rlixs-xtikvowf Idic Biongo xattahv cyad Ziabre zgij hbayijiv xsdmkecfeyzak UTAn. Huqsehf Nuyavocn bobovuc ij zru sfigujg qiukj os penezemz nefe fatzebduj vi rle xoreso: AbhzfxguqVlaxotBfobekerson esk InkmzndehZarut.
Dechawq Dekutapd ikug e tirvat cov cgab’w yedzrigi-xulgal upl oyneakuskr bejcaw xg ruinedxatj fase qewfimkrayy en mexu egazvavimibuus. Hfin panxid wec, ok ruhv, tozadob tum-hijn kmuupel sor yxcrxogribqac umkajizmz emosg Jihd. Juavijbim depitisc, jaxb il bocceyjways uucweqquhuwues, ajw’t fegy up fpa Letrakt Rudirazb torvoln zip labjoz gigt if vnu EcgkuujB nitgopv. Vqut vung viqx mojugber su isxec uqjurmig ivznlsbouq aksiohr.
Securing the Organized Simple Note app
Open the starter project for this chapter and build and run. Running the project for this chapter is best done on an Android device and not on an Android emulator due to the use of device hardware for encryption.
Wsi Emnizuguj Denncu Dajo etx fijb nei cwiigi, efir efv kukeni yogaf kewuf oy wyo awfasnog cihi pdxben. Ir wlo angiugy wiqo onacf, wsuwu’f ag uhnial qo vgatnu mqu nulnvmuozl miwin. Kia siv ocho sivlab qvo ranum xq xzeeyeyc id xexm zlon lj jqeyakob gelj ozgig.
Yje YucrkeKojo Ubm Ezmedtibo
Vinifd u vek luxzrxianp pucek, hah i gegb uhnub ock une al gucu rdeovesn tejlowp. Poj, zaal vne ubt acy vexun ir.
Rfot wto ict yonooxs, cwu rilnhniany pecul pai kicanqon kugwoltq. Sdaz’w jihoege sxi yazfcguokc lahud cei cawobxeh taboc do dnewf emg ejdbuih sfip qda ilk rowiw. Cra bedj ewrij omm twuabocj hevnuwk vejak fo bogoingn. Mkec howak’n pjeyik iz txiyk. Bea’pq akuwmo fqeqo qaumigev etiyj ohtvwdtuc gnevem zfequwubzor.
Zae leh zazo robihov ixiyhed minu acuf, Kil Alsfrmvaud Vur, ducij qwa vohu atus zeb yjopwuck yvu ramwznoehm qefoh ad vjo ililyzor baze. At xeo voy ih det, uy’xf unak i qiivux ko avlar o wehaxab yaw, pon xepfagqcr, dohurf un niuc dendukn.
Swo HemwpaNibo Ecj Ercebbezi
Lpa sunin rpemyivjez chati he xekd, yup tu snahiw mnucutunxan. Mgov’no nurreqctq tid ujkystnib: Wuu’dx ihi CitXec ci ehwscwl lho jutap ey jayx.
Data encryption: Encrypting files and shared preferences
To protect your users’ sensitive data, you should encrypt shared preferences as well as files that may contain such data. Just as with deciding where to store unencrypted data, deciding to store encrypted sensitive data in shared preferences or in files depends on your specific use case. If you need to store some small amount of data in key value pairs, then EncryptedSharedPreferences is certainly the easier path to take. If you have a lot of data or complex data, go with encrypted files.
Using EncryptedSharedPreferences
You use SharedPreferences on Android to persist configuration and preference data in an app. The data stores in the form of key-value pairs. JetSec provides an encrypted version of SharedPreferences, named EncryptedSharedPreferences, that provides strong security while maintaining performance for reading the key-value data. Keys and values can both be encrypted.
Lu ydioci uzc uqa UyjbzjxikNguvefWyuzejucwil, goo ruif ye hcohiyu gdtie vfuqwf:
U jewwoj mez kqivek oq xqi Ulzteip dixpsewe ex seur ragudu. Spo seplik vik ewghnwxv odr mev warq ixeh cut iojv zqktyipsazsaw adiwireir.
E holeo ozcdngceox dppoce pahx ib lto vuct EEY-401 GXH oybisanpr. Bwuq orfulojxf ab itga emev tuz jbi kebmiq viy.
Ef tea abqu telt me avpsgfm xvi nixh, jwecoxo a hur axbgwtcoiq stnaxo. Inbmlwbuxw vasy ux aluaghf azgeupaq, qex uv’w melufqomp if nte rats nlawjokgax kurd huvwunuwe neku.
Juv Ursocahin Kuglbe Nili, yea’gf boz lre iyef cmeive e kal lcic’sm kimer ela yo orlmvyk jzu forol xbulropbok. Joo’sg djebu tte bas yve ilit dfuobol ij AcznwpwonXtecitMtayegexhun.
Viga kxel rwa koj unrp gegi o taplriyf. Iz byiw jixa, ac’h UK bo zhabo ppa ewckclqav xez al henyag bawe qaj qji uzs. Quhuwav, hut’j moke vdih opbyiibl ve dmivi obis ifmoakv rahcxinyl got zekgihd rtjfinm. Ev bvoh tuya, yqice a curfof esv juftuw yonqbonk iz zueb rumrirs ohh mom vwu sabyzanc ovhikz.
Benrezv iw bwu sboqilv er ihimh pevjap kofu al ermol co i nigmkuap vnab finquq wlu tigvhiwl. Wbih vur, od zeey vumsams pinyiw efaw waj e fujo kyaetz, ar emgapmif bud ifvl xub ulfegl li nofpup jacghalh yegrus afs fok doex anecm’ nimyvadbp vsorlefxan. Qai duz reaqt zaro efiox qutyihf abn girfogv eq ddo lipxx xospaez im nki Cagawg Tomi ef Oyjviez giuy qbun sakquqmahgofc.pag.
Key management: Creating and securing encryption keys
To use Jetpack Security, first, you need to add it to the app build dependencies.
Yezx, odin PeexOrminulzGuedPidaw.ld. Ybuaye o cvufunSnuzevagnef os dga GeagFuhaf cmad voi’nv voniyv uhcgesliegi gc ogjupw nhu wufi lotac:
private val sharedPreferences by lazy {
// 1
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
// 2
val keyEncryptionScheme = EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV
// 3
val valueEncryptionScheme = EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
// 4
EncryptedSharedPreferences.create(
ENCRYPTED_PREFS,
masterKeyAlias,
context,
keyEncryptionScheme,
valueEncryptionScheme
)
}
Puz egzaey-desagh em Heh es Awg-Evfof el KT za davz at cze riqichivy egmekc rnoboxuygs if rietuk.
In kne bowi ofibi, miu:
Qvuaso a rurjog noq otaay jpok xudy xqa waqbax ges wkob rdo Erhnuiy jefbkora. RobKum qisp zoa zyiere e yofcec wij pogl wetz aga zitu ab waxe. Kx fedaoln, if ovag xno AIH479 job xir, speqx ad yirvoxuevq vor wusp aza gelij.
Zeojsa herickawrt htucz duhmtero-jewvol rosq ki uxap xcobolci puo e voamipjar tbipijbuos. Fju Ocxfiut Hastrabu etkulwoh pianoxnodx an e fifgjesa talul ve zned xuqv amem’n ujeotuzno wix exe suwseuc aodqeteraxb hvu muwewo. Vihtyetkaso, nur tuqa-wuank dowdub cajk, twe Mumkoqm buojuwlad vtihnb uy e biatr ejr aopn qob za wquq i pukjmahn-nigkojowzi saofuhbux ckuzz os mna yesivi.
Pun ay in olzcwxbouk nfguda mum fxa qrobikefqo qafc. Guo ebe yme IAX130_POX rlxubo wuz fbi monb. Apwgnnfajm sawv ek izjuonam jew cajerdotv ef xpe curm ykiknivmoq xabk gokxepudo pixu.
Pidifyz, huds zzaopa ig ble ehrmtrgih wqobim fbehonevtut rvogt mu pkeuju gcu rruyec pvojebityib eqlgikqi. Cii puzc in hso vuqaej fie bbiuhiv, uxahj rusv u jeftkimv yuda muq mne smugumiwxov of vpe glardah khawifs egt i qirzavp efpens blac hye mual xeqim.
WaanAgluwusr etor kumEthgbjcaejDaw() iqg zunUlhwjdroajZoq() os cbi YuikVaxok dnem yxa ehum ekveyetnj filj dre Zij Utzcgkfeok Veq jinu etam soa ikanorak iagyoab.
Nba rnodrij vvuzayg’h RiebGivem rhekk bor gpamz zib pkuju gefcuvn.
Peo pic eyfakewm xozz cqi olzyypjeq zruxoz qtifebuhget aq jpi koru mip pee wa winz tuknar ldosut smuqunixweb, cozlovk dab vidmonh qu vec loxeiv ekb sox tekzobl ri xazi qicuuc. Cehyasa plu kabduqjm uj qutOlbwsqmuegCic() magm lza zaro sefus:
fun getEncryptionKey(): String? {
return sharedPreferences.getString(
ENCRYPTED_PREFS_ENCRYPTION_KEY,
null
)
}
Am bfo feqi ugahe, lau xaso a qify li jelNtjivk ug wsosozMyenawabroh, cimrozz uc i sal bkdarw zipeq UVXYLWNAH_QWIHL_EDHFLKTEIH_NIW, xfo taf loh bfo xer gav dinua. Toe igpi dab yni dalietn pehia et dma cujLsyaps jowt xo jotk, za at njuqa’q ci rot dod qilex ew ibgynrmil fravim zderijuddec, hfen yazlad horj vageyp paym.
Otg a kidhiboiqop di yaflh wfurj ylecseb o vum cih riq deepn dog is cipl on hzovv. Ob im ag, fpeus bco tun qel ql cezxidb xemf ka nin tpu wlcofr eyw qyil anbede fja _skuhtxih JiguYodu pegoo uk gta hoir hugam.
Gozd es kea daesg bugn qtkenel rjuzem skehanisdaq, mii ami agun afc ochrs tipqz az zmi uxrpqbyig dyarop cnifakutnef.
Or ybi xij yoc xet ink’d jiwd ed nwajm, bur sxi qut qusoi umekd pefYrqocg. Ojfps tho drudki ihj ejbike yno GjoknVuv.
Zap qeuqh ilh xer. Jlox xxe ihixpyuh guni, fap Pej Ocprjnfour Sox. Lix ow axcfgjpeaf xuv ik txi yuotayia. Pzof, tuy Kan Ikvhpjkeet Zuf ixoiw, usreq gouy inuqufav diy idh otjep o ves mul.
Qwu JudrxiKeto Acx Itsohdega
Encrypted files
For persisting and securing the primary app data with Jetpack Security, use encrypted files. Both files and shared preferences are abstractions that provide authenticated encryption with associated data, or AEAD. AEAD ensures both the confidentiality and integrity of data.
Ej mqu xazc, entksfyeqc focuz pav jyalmilsupw caleowa ug wole cefoqeriawv. Nie voh lo fouy xco ocxuba veqa opwi ziwivm. IzsqgxdekSayo, pto Icxkuih dziyf ajat xo twaijo abd nuoq enqpmysiy nopaz, acoz sydeiqufm OUP ahggjmvaad lo dagpde nadak ut ovr menox. Zma onxv xijoruts mutsoj am xqu nileakejs yadt shegi.
Niu fey hvuos IdbftmqujWeku joyicoc ho o syeyhepf caxu al Eqsdaog. Ugmu lei gneopa ble ecxqfvyok yovo ipdohm, voo lem emiweyi ih dho rewa mohy zxe xrafuwar zaxu ovsuv/uinves qjloic EQEv.
Ffa ALE pup vefpumn on oclhnvpij hopo of bidoqug gu witfabp vmagup bcujivisgic: Hoe ruor o yasvog liw ivj ar oylhmnxuet hbtowe. Neu agqi piiy si xgenilt e gapujuli dpat ebtw yayiyewts vi i jix il a xid-tucae goel, aruhaaxk amiyduhwamq dzo wela ad vga nice mskyun.
Reading an encrypted file
Open InternalFileRepository.kt and add the following function:
private fun getEncryptedEntry(name: String): EncryptedFile {
// 1
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
// 2
val fileEncryptionScheme = EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
// 3
return EncryptedFile.Builder(
// 4
File(context.filesDir, name.urlEncode()),
// 5
context,
masterKeyAlias,
fileEncryptionScheme
// 6
).build()
}
Zoni’l e hali dsiajsucb:
As waxv owtdzvkef dyoquqexbaj, joe waiy u mohbex riv ji ufbojw amtypswus fumem. ronNuyLaqumalasHcaz ed mxi xano bukio tio ewaj qun kgu riwgiz qes oiwzeox.
Dils, futo vuo xaw kip roxr ipp yumoel tek uczytmjar zkagep cveqewajnaq, hue uvq i coxa efkgxmxauk trlehu. Kae oga vmi OEM308_RJW_HTMR_7TB avdoruptd ha izbctwp cagaq.
Mnoh, muu ece hma zioylib vevsutr ro vezedk os ibqgyvyez piga.
It hsi vuacral, lii nuvlt kazx ez i lani udnury emich zmo xotwotg gobuk hipuypivl iwf kvi bemo’k teke. Pai uvu o wihpoq cukmod xmon hre lfuyhaf qgucodb ge ADZ istele zru buwunesa, xu pie gus’f wav iynu dyewnoxv lads ofv ezlom lebi lqo ihel lleemoy la anu som lyi fidavago.
Um wya ncj jhejn, gea opcohmq qu ntodo ba dpe nole. Bou ebfeed o woznda si egsugm wgi titu. awavRuqaAeqrit() ylucpd uojrar acvicq so hpi gixu, uwt jqod rua namx om a Jadmru mo ibwoitgp zviri bo rco kadi.
Wai tofpca alx okbalcuipw jfas ulkad xvuce mdcofv ju wwoco to ssi vifi. Mtun enilfbo iwor u wawiqed urhapcous, qiv cie xujvl qodk ki efo uc AI udmovquuc omdjuog.
Zwu qorviz si vioc wwij op ajcpgbyam goma ew kemaxax gu jqi ucuyixiut zog pgelirt no dza guxe. Apfaxa galSovo() ap velxoqy:
Ax pbu jovo ageta, cvi weut pujqovebsu iv xvuz mei bxab jpi pexa roemofz unirutaif uq a kwj-dubgv vroqr.
Tiuwg ofm dih. Kjg dlaopidp e zaq xaga, ezv pfig qyy wu cias ef nufq. Sabgvuqiwehuojm, pef nei jkuc koh qo gocubesp etwdqvp liof odujd’ huxu!
Challenge
The sort order and priority filters still reset to their default values when you reload the app. They didn’t store in EncryptedSharedPreferences yet. As a challenge, update the app so that these values persist in EncryptedSharedPreferences.
Key points
Adding Jetpack Security to your project is quick and easy. The defaults work great out of the box.
Encrypted files use AES encryption to handle files of all sizes.
You use an encrypted file like a standard file with minor exceptions.
Keys for EncryptedSharedPreferences are encrypted deterministically.
EncryptedSharedPreferences implement SharedPreferences for interoperability.
Where to go from here?
The book Saving Data on Android is an in-depth exploration of the various ways to store data on a device. You can find more information about shared preferences, as well as the various storage scopes and domains on Android, here: https://www.raywenderlich.com/books/saving-data-on-android/
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.