Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to secure data in Android

How to secure data in Android

What data you may want to secure ?
Encryption
Encryption on Android
Android KeyStore Provider
Security Utility

Yakiv Mospan

April 21, 2016
Tweet

More Decks by Yakiv Mospan

Other Decks in Programming

Transcript

  1. How to secure data in Android? “Security is the degree

    of resistance to, or protection from, harm” Yakiv Mospan http://www.yakivmospan.com/ Team Technologies
  2. Overview What data you want to secure ? Encryption Encryption

    on Android Android Keystore Provider Security Utilitу
  3. Overview What data you want to secure ? Encryption Encryption

    on Android Android Keystore Provider Security Utilitу
  4. Overview What data you want to secure ? Encryption Encryption

    on Android Android Keystore Provider Security Utilitу
  5. Overview What data you want to secure ? Encryption Encryption

    on Android Android Keystore Provider Security Utilitу
  6. Overview What data you want to secure ? Encryption Encryption

    on Android Android Keystore Provider Security Utilitу
  7. Data Sensitive data personal life information, physical or mental health

    details, criminal or civil offences, private photos, private user documents, etc. Financial data accounts, transactions, reports, credit card information, etc. Credentials usernames, passwords, touch pincodes, fingerprint data, and all other stuff that can provide access to data above.
  8. Data Sensitive data personal life information, physical or mental health

    details, criminal or civil offences, private photos, private user documents, etc. Financial data accounts, transactions, reports, credit card information, etc. Credentials usernames, passwords, touch pincodes, fingerprint data, and all other stuff that can provide access to data above.
  9. Data Sensitive data personal life information, physical or mental health

    details, criminal or civil offences, private photos, private user documents, etc. Financial data accounts, transactions, reports, credit card information, etc. Credentials usernames, passwords, touch pincodes, fingerprint data, and all other stuff that can provide access to data above.
  10. Security tips “In general, we recommend minimizing the frequency of

    asking for user credentials—to make phishing attacks more conspicuous, and less likely to be successful. Instead use an authorization token and refresh it.”
  11. Security tips “Where possible, username and password should not be

    stored on the device. Instead, perform initial authentication using the username and password supplied by the user, and then use a short-lived, service- specific authorization token.”
  12. Encryption Encryption is the most effective way to achieve data

    security. To read an encrypted file, you must have access to a secret key or password that allows you to decrypt it. Unencrypted data is called plain text, encrypted data is referred to as cipher text.
  13. How it works Plain text password Algorithm aes, rsa, des,

    etc. Key specific for algorithm Сipher text sh7aertscaasees...
  14. How it works Plain text password Algorithm aes, rsa, des,

    etc. Key specific for algorithm Сipher text sh7aertscaasees...
  15. How it works Plain text password Algorithm aes, rsa, des,

    etc. Key specific for algorithm Сipher text sh7aertscaasees...
  16. Algorithm types Symmetric The oldest and best-known technique. The encryption

    key and the decryption key are the same. Asymmetric A modern branch of cryptography. also known as public-key cryptography in which the algorithms employ a pair of keys (a public key and a private key) and use a different component of the pair for different steps of the algorithm.
  17. Algorithm types Symmetric The oldest and best-known technique. The encryption

    key and the decryption key are the same. Asymmetric A modern branch of cryptography. also known as public-key cryptography in which the algorithms employ a pair of keys (a public key and a private key) and use a different component of the pair for different steps of the algorithm.
  18. Algorithm types Stream cipher A symmetric encryption algorithm that processes

    the data a bit or a byte at a time with a key resulting in a randomized ciphertext or plaintext. Block cipher Deterministic algorithm operating on fixed-length groups of bits, called blocks. Block ciphers are important elementary components in the design of many cryptographic protocols, and are widely used to implement encryption of bulk data.
  19. Algorithm types Stream cipher A symmetric encryption algorithm that processes

    the data a bit or a byte at a time with a key resulting in a randomized ciphertext or plaintext. Block cipher Deterministic algorithm operating on fixed-length groups of bits, called blocks. Block ciphers are important elementary components in the design of many cryptographic protocols, and are widely used to implement encryption of bulk data.
  20. Block cipher Modes A mode of operation describes how to

    repeatedly apply a cipher's single-block operation to securely transform amounts of data larger than a block. Padding Block cipher works on units of a fixed size (known as a block size), but messages come in a variety of lengths. So some modes (namely ECB and CBC) require that the final block be padded before encryption. Initialization vector (IV) Block of bits that is used by several modes to randomize the encryption and hence to produce distinct ciphertexts even if the same plaintext is encrypted multiple times, without the need for a slower re-keying process.
  21. Block cipher Modes A mode of operation describes how to

    repeatedly apply a cipher's single-block operation to securely transform amounts of data larger than a block. Padding Block cipher works on units of a fixed size (known as a block size), but messages come in a variety of lengths. So some modes (namely ECB and CBC) require that the final block be padded before encryption. Initialization vector (IV) Block of bits that is used by several modes to randomize the encryption and hence to produce distinct ciphertexts even if the same plaintext is encrypted multiple times, without the need for a slower re-keying process.
  22. Block cipher Modes A mode of operation describes how to

    repeatedly apply a cipher's single-block operation to securely transform amounts of data larger than a block. Padding Block cipher works on units of a fixed size (known as a block size), but messages come in a variety of lengths. So some modes (namely ECB and CBC) require that the final block be padded before encryption. Initialization vector (IV) Block of bits that is used by several modes to randomize the encryption and hence to produce distinct ciphertexts even if the same plaintext is encrypted multiple times, without the need for a slower re-keying process.
  23. Key types Secret key A single secret key which is

    used in conventional symmetric encryption which is used to encrypt and decrypt a message. Private key The secret component of a pair of cryptographic keys used for decryption in asymmetric cryptography. Public key The public component of a pair of cryptographic keys used for encryption in asymmetric cryptography.
  24. Common algorithms RSA A public-key encryption algorithm and the standard

    for encrypting data sent over the internet. AES The Advanced Encryption Standard (AES) is the algorithm trusted as the standard by the U.S. Government and numerous organizations.
  25. Common modes ECB Electronic Codebook, the simplest of the encryption

    modes. The message is divided into blocks, and each block is encrypted separately. CBC Cipher Block Chaining, each ciphertext block depends on all plaintext blocks processed up to that point. To make each message unique, an initialization vector must be used in the first block.
  26. JCA APIs for digital signatures, message digests (hashes) APIs for

    certificates and certificate validation APIs for encryption (symmetric/asymmetric block/stream ciphers) APIs for key generation and management, and secure random number generation
  27. JCA APIs for digital signatures, message digests (hashes) APIs for

    certificates and certificate validation APIs for encryption (symmetric/asymmetric block/stream ciphers) APIs for key generation and management, and secure random number generation
  28. JCA APIs for digital signatures, message digests (hashes) APIs for

    certificates and certificate validation APIs for encryption (symmetric/asymmetric block/stream ciphers) APIs for key generation and management, and secure random number generation
  29. JCA APIs for digital signatures, message digests (hashes) APIs for

    certificates and certificate validation APIs for encryption (symmetric/asymmetric block/stream ciphers) APIs for key generation and management, and secure random number generation
  30. Provider Defines a set of extensible and implementation - independent

    API’s. New algorithms or behaviors can be supplied by adding new provider with its own API implementation.
  31. Provider Defines a set of extensible and implementation - independent

    API’s. New algorithms or behaviors can be supplied by adding new provider with its own API implementation.
  32. Provider // get all available providers Provider[] providers = Security.

    getProviders(); for (Provider provider : providers) { // get provider info String name = provider.getName(); String info = provider.getInfo(); double version = provider.getVersion(); // get all services that you can use with this provider Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { // get service info String type = service.getType(); String className = service.getClassName(); String algorithm = service.getAlgorithm(); } }
  33. Provider // get all available providers Provider[] providers = Security.

    getProviders(); for (Provider provider : providers) { // get provider info String name = provider.getName(); String info = provider.getInfo(); double version = provider.getVersion(); // get all services that you can use with this provider Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { // get service info String type = service.getType(); String className = service.getClassName(); String algorithm = service.getAlgorithm(); } }
  34. Provider // get all available providers Provider[] providers = Security.

    getProviders(); for (Provider provider : providers) { // get provider info String name = provider.getName(); String info = provider.getInfo(); double version = provider.getVersion(); // get all services that you can use with this provider Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { // get service info String type = service.getType(); String className = service.getClassName(); String algorithm = service.getAlgorithm(); } }
  35. Provider // get all available providers Provider[] providers = Security.

    getProviders(); for (Provider provider : providers) { // get provider info String name = provider.getName(); String info = provider.getInfo(); double version = provider.getVersion(); // get all services that you can use with this provider Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { // get service info String type = service.getType(); String className = service.getClassName(); String algorithm = service.getAlgorithm(); } }
  36. Provider // get all available providers Provider[] providers = Security.

    getProviders(); for (Provider provider : providers) { // get provider info String name = provider.getName(); String info = provider.getInfo(); double version = provider.getVersion(); // get all services that you can use with this provider Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { // get service info String type = service.getType(); String className = service.getClassName(); String algorithm = service.getAlgorithm(); } }
  37. SecureRandom SecureRandom secureRandom = new SecureRandom(); byte[] b = new

    byte[] { (byte) 1 }; secureRandom.setSeed(b); int output = secureRandom.nextInt();
  38. SecureRandom SecureRandom secureRandom = new SecureRandom(); byte[] b = new

    byte[] { (byte) 1 }; secureRandom.setSeed(b); int output = secureRandom.nextInt(); Specifying a fixed seed will cause the instance to return a predictable sequence of numbers.
  39. KeyGenerator // generate a 256-bit key final int keyLength =

    256; // automatically seeded from system entropy. SecureRandom secureRandom = new SecureRandom(); KeyGenerator generator = KeyGenerator. getInstance("AES", "BC"); generator.init(keyLength, secureRandom); SecretKey key = generator.generateKey();
  40. What provider to use KeyGenerator // generate a 256-bit key

    final int keyLength = 256; // automatically seeded from system entropy. SecureRandom secureRandom = new SecureRandom(); KeyGenerator generator = KeyGenerator. getInstance("AES", "BC"); generator.init(keyLength, secureRandom); SecretKey key = generator.generateKey(); What algorithm to use
  41. KeyGenerator // generate a 256-bit key final int keyLength =

    256; // automatically seeded from system entropy. SecureRandom secureRandom = new SecureRandom(); KeyGenerator generator = KeyGenerator. getInstance("AES"); generator.init(keyLength, secureRandom); SecretKey key = generator.generateKey(); Use first provider that has “AES” algorithm implementation
  42. KeyGenerator // generate a 256-bit key final int keyLength =

    256; // automatically seeded from system entropy. SecureRandom secureRandom = new SecureRandom(); KeyGenerator generator = KeyGenerator. getInstance("AES"); generator.init(keyLength, secureRandom); SecretKey key = generator.generateKey();
  43. KeyGenerator // generate a 256-bit key final int keyLength =

    256; KeyGenerator generator = KeyGenerator. getInstance("AES"); generator.init(keyLength); SecretKey key = generator.generateKey(); We can use engine default secure random instead
  44. KeyGenerator // generate a 256-bit key final int keyLength =

    256; KeyGenerator generator = KeyGenerator. getInstance("AES"); generator.init(keyLength); SecretKey key = generator.generateKey();
  45. KeyPairGenerator An engine class which is capable of generating a

    private key and its related public key utilizing the algorithm it was initialized with.
  46. KeyPairGenerator // generate a 1024-bit key final int keyLength =

    1024; KeyPairGenerator generator = KeyPairGenerator. getInstance("RSA"); generator.initialize(keyLength); KeyPair keyPair= generator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate();
  47. KeyPairGenerator // generate a 1024-bit key final int keyLength =

    1024; KeyPairGenerator generator = KeyPairGenerator. getInstance("RSA"); generator.initialize(keyLength); KeyPair keyPair= generator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); Key for encryption Key for decryption
  48. Cipher Provides access to implementations of cryptographic ciphers for encryption

    and decryption. To get instance of Cipher, you need to specify transformation Transformation specifies an operation (or a set of operations) as a string in the form: "algorithm/mode/padding" or "algorithm".
  49. Cipher Provides access to implementations of cryptographic ciphers for encryption

    and decryption. To get instance of Cipher, you need to specify transformation Transformation specifies an operation (or a set of operations) as a string in the form: "algorithm/mode/padding" or "algorithm".
  50. Cipher Provides access to implementations of cryptographic ciphers for encryption

    and decryption. To get instance of Cipher, you need to specify transformation Transformation specifies an operation (or a set of operations) as a string in the form: "algorithm/mode/padding" or "algorithm".
  51. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT); Text for encryption SecretKey or PublicKey
  52. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT); Provider default Mode and Padding are used
  53. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding" ); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT); Full transformation
  54. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT); Initialize cipher for encryption
  55. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT); Encrypts data
  56. Encryption String plainText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding" ); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainData = plainText.getBytes( UTF_8); byte[] cipherData = decode(cipher, plainData); String cipherText = Base64. encodeToString(cipherData, Base64.DEFAULT);
  57. Decryption String cipherText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] cipherData = Base64. decode(cipherText, Base64.DEFAULT); byte[] plainData = decode(cipher, cipherData); String plainText = new String(decodedData, UTF_8); Encrypted text SecretKey or PrivateKey
  58. Decryption String cipherText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding" ); cipher.init(Cipher.DECRYPT_MODE, key); byte[] cipherData = Base64. decode(cipherText, Base64.DEFAULT); byte[] plainData = decode(cipher, cipherData); String plainText = new String(decodedData, UTF_8); Initialize cipher for decryption
  59. Decryption String cipherText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] cipherData = Base64. decode(cipherText, Base64.DEFAULT); byte[] plainData = decode(cipher, cipherData); String plainText = new String(decodedData, UTF_8); Decrypts data
  60. Decryption String cipherText = ...; Key key = ...; Cipher

    cipher = Cipher. getInstance("AES/CBC/PKCS7Padding" ); cipher.init(Cipher.DECRYPT_MODE, key); byte[] cipherData = Base64. decode(cipherText, Base64.DEFAULT); byte[] plainData = decode(cipher, cipherData); String plainText = new String(decodedData, UTF_8);
  61. decode(cipher, data) ByteArrayOutputStream baos = new ByteArrayOutputStream(); CipherOutputStream output =

    new CipherOutputStream(baos, cipher); output.write(data); output.close(); return baos.toByteArray();
  62. KeyStore Database with a well secured mechanism of data protection,

    that is used to save, get and remove keys.
  63. Create String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore.

    getInstance(defaultType); keyStore.load(null); Get default keystore provider
  64. Create String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore.

    getInstance(defaultType); keyStore.load(null); Initializes empty keystore
  65. Create Context context = ...; String keystoreName = ...; String

    keystorePassword = ...; File keystoreFile = new File(context.getCacheDir(), keystoreName); String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore. getInstance(defaultType); if (!keystoreFile.exists()) { keyStore.load(null); } else { keyStore.load(new FileInputStream(keystoreFile), keystorePassword); }
  66. Create Context context = ...; String keystoreName = ...; String

    keystorePassword = ...; File keystoreFile = new File(context.getCacheDir(), keystoreName); String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore. getInstance(defaultType); if (!keystoreFile.exists()) { keyStore.load(null); } else { keyStore.load(new FileInputStream(keystoreFile), keystorePassword); } Keystore location
  67. Create Context context = ...; String keystoreName = ...; String

    keystorePassword = ...; File keystoreFile = new File(context.getCacheDir(), keystoreName); String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore. getInstance(defaultType); if (!keystoreFile.exists()) { keyStore.load(null); } else { keyStore.load(new FileInputStream(keystoreFile), keystorePassword); } Load keystore from file
  68. Create Context context = ...; String keystoreName = ...; String

    keystorePassword = ...; File keystoreFile = new File(context.getCacheDir(), keystoreName); String defaultType = KeyStore. getDefaultType(); KeyStore keyStore = KeyStore. getInstance(defaultType); if (!keystoreFile.exists()) { keyStore.load(null); } else { keyStore.load(new FileInputStream(keystoreFile), keystorePassword); }
  69. Save Symmetric String storePassword = ...; File keystoreFile = ...;

    KeyStore keyStore = createKeyStore(); SecretKey key = createSymmetricKey(); String keyAlias= ...; String keyPassword = ...; SecretKeyEntry keyEntry = new SecretKeyEntry(key); keyStore.setEntry(keyAlias, keyEntry, new PasswordProtection(keyPassword)); keyStore.store(new FileOutputStream(keystoreFile), storePassword); Key entry password for given alias Keystore entry “key”
  70. Save Symmetric String storePassword = ...; File keystoreFile = ...;

    KeyStore keyStore = createKeyStore(); SecretKey key = createSymmetricKey(); String keyAlias= ...; String keyPassword = ...; SecretKeyEntry keyEntry = new SecretKeyEntry(key); keyStore.setEntry(keyAlias, keyEntry, new PasswordProtection(keyPassword)); keyStore.store(new FileOutputStream(keystoreFile), storePassword); Create and add new entry to keystore
  71. Save Symmetric String storePassword = ...; File keystoreFile = ...;

    KeyStore keyStore = createKeyStore(); SecretKey key = createSymmetricKey(); String keyAlias= ...; String keyPassword = ...; SecretKeyEntry keyEntry = new SecretKeyEntry(key); keyStore.setEntry(keyAlias, keyEntry, new PasswordProtection(keyPassword)); keyStore.store(new FileOutputStream(keystoreFile), storePassword); Write new added key entry to keystore
  72. Save Symmetric String storePassword = ...; File keystoreFile = ...;

    KeyStore keyStore = createKeyStore(); SecretKey key = createSymmetricKey(); String keyAlias= ...; String keyPassword = ...; SecretKeyEntry keyEntry = new SecretKeyEntry(key); keyStore.setEntry(keyAlias, keyEntry, new PasswordProtection(keyPassword)); keyStore.store(new FileOutputStream(keystoreFile), storePassword);
  73. Save Asymmetric KeyPair keyPair = createAsymmetricKey(); PrivateKey key = keyPair.getPrivate();

    X509Certificate certificate = createCertificate(keyPair); KeyStore keyStore = createKeyStore(); keyStore.setKeyEntry(keyAlias, key, keyPassword, new Certificate[]{certificate}); keyStore.store(new FileOutputStream(keystoreFile), storePassword); We need to generate public certificate for private key
  74. Save Asymmetric KeyPair keyPair = createAsymmetricKey(); PrivateKey key = keyPair.getPrivate();

    X509Certificate certificate = createCertificate(keyPair); KeyStore keyStore = createKeyStore(); keyStore.setKeyEntry(keyAlias, key, keyPassword, new Certificate[]{certificate}); keyStore.store(new FileOutputStream(keystoreFile), storePassword); Add new key entry to keystore with public certificate
  75. Save Asymmetric KeyPair keyPair = createAsymmetricKey(); PrivateKey key = keyPair.getPrivate();

    X509Certificate certificate = createCertificate(keyPair); KeyStore keyStore = createKeyStore(); keyStore.setKeyEntry(keyAlias, key, keyPassword, new Certificate[]{certificate}); keyStore.store(new FileOutputStream(keystoreFile), storePassword);
  76. Certificate There is no public API to generate self signed

    Certificate programmatically Use Bouncy Castle library to generate Certificate compile 'org.bouncycastle:bcprov-jdk15on:$bouncycastle_version' You also can load you Certificate from a file
  77. Certificate There is no public API to generate self signed

    Certificate programmatically Use Bouncy Castle library to generate Certificate compile 'org.bouncycastle:bcprov-jdk15on:$bouncycastle_version' You also can load you Certificate from a file
  78. Certificate There is no public API to generate self signed

    Certificate programmatically Use Bouncy Castle library to generate Certificate compile 'org.bouncycastle:bcprov-jdk15on:$bouncycastle_version' You also can load you Certificate from a file
  79. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger .ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm("SHA256WithRSAEncryption"); return gen.generate(privateKey, "BC");
  80. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger.ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm("SHA256WithRSAEncryption"); return gen.generate(privateKey, "BC"); Describes the entity associated with the public key
  81. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger.ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm("SHA256WithRSAEncryption"); return gen.generate(privateKey, "BC"); Time interval Certificate is valid on
  82. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger.ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm( "SHA256WithRSAEncryption" ); return gen.generate(privateKey, "BC"); Algorithm to sign certificate with
  83. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger.ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm("SHA256WithRSAEncryption"); return gen.generate(privateKey, "BC"); Required by Bouncy Castle library
  84. createCertificate(keyPair) Calendar start = Calendar. getInstance(); Calendar end = Calendar.

    getInstance(); end.add(Calendar.YEAR, 1); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); X500Principal principal = new X500Principal("CN=" + alias + " CA"); X509V3CertificateGenerator gen = new X509V3CertificateGenerator(); gen.setPublicKey(publicKey); gen.setSerialNumber(BigInteger .ONE); gen.setSubjectDN(principal); gen.setIssuerDN(principal); gen.setNotBefore(start.getTime()); gen.setNotAfter(end.getTime()); gen.setSignatureAlgorithm( "SHA256WithRSAEncryption" ); return gen.generate(privateKey, "BC");
  85. Load Certificate CertificateFactory fc = CertificateFactory. getInstance("X.509"); InputStream is =

    new FileInputStream("certificate.cer"); X509Certificate cert = (X509Certificate) fc.generateCertificate(is);
  86. Get symmetric key KeyStore keyStore = createKeyStore(); SecretKey key =

    (SecretKey) keyStore.getKey(alias, password);
  87. Get asymmetric key KeyStore keyStore = createDefaultKeyStore(); PasswordProtection protection =

    new PasswordProtection(password); PrivateKeyEntry entry = (PrivateKeyEntry) keyStore.getEntry( alias, protection); if(entry != null) { PublicKey publicKey = entry.getCertificate().getPublicKey() KeyPair keyPair = new KeyPair(publicKey, entry.getPrivateKey()); }
  88. Android Keystore Provider Lets an individual app to store its

    own credentials, that only the app itself can access.
  89. Provider Added in 18 API level Uses system keystore (more

    secure) Asymmetric keys available from 18 API Generates self signed certificate for you Google used the same Bouncy Castle library. They did copy sources but have made them private Symmetric keys available from 23 API
  90. Provider Added in 18 API level Uses system keystore (more

    secure) Asymmetric keys available from 18 API Generates self signed certificate for you Google used the same Bouncy Castle library. They did copy sources but have made them private Symmetric keys available from 23 API
  91. Provider Added in 18 API level Uses system keystore (more

    secure) Asymmetric keys available from 18 API Generates self signed certificate for you Google used the same Bouncy Castle library. They did copy sources but have made them private Symmetric keys available from 23 API
  92. Provider Added in 18 API level Uses system keystore (more

    secure) Asymmetric keys available from 18 API Generates self signed certificate for you Google used the same Bouncy Castle library. They did copy sources but have made them private Symmetric keys available from 23 API
  93. Provider Added in 18 API level Uses system keystore (more

    secure) Asymmetric keys available from 18 API Generates self signed certificate for you Google used the same Bouncy Castle library. They did copy sources but have made them private Symmetric keys available from 23 API
  94. KeyPairGeneratorSpec 500Principal subject = ...; KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)

    .setAlias(alias) .setSerialNumber(serialNumber) .setSubject(subject) .setStartDate(startDate) .setEndDate(endDate) .build(); if(Build.VERSION.SDK_INT > Build.VERSION_CODES. JELLY_BEAN_MR2){ builder.setKeySize(keySize); } KeyPairGenerator generator = KeyPairGenerator. getInstance( "RSA", "AndroidKeyStore"); generator.initialize(spec); KeyPair keyPair= generator.generateKeyPair(); Setup key parameters Available only from 19 API
  95. KeyPairGeneratorSpec 500Principal subject = ...; KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)

    .setAlias(alias) .setSerialNumber(serialNumber) .setSubject(subject) .setStartDate(startDate) .setEndDate(endDate) .build(); if(Build.VERSION.SDK_INT > Build.VERSION_CODES. JELLY_BEAN_MR2){ builder.setKeySize(keySize); } KeyPairGenerator generator = KeyPairGenerator. getInstance( "RSA", "AndroidKeyStore" ); generator.initialize(spec); KeyPair keyPair= generator.generateKeyPair(); Set Android Keystore Provider
  96. KeyPairGeneratorSpec 500Principal subject = ...; KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)

    .setAlias(alias) .setSerialNumber(serialNumber) .setSubject(subject) .setStartDate(startDate) .setEndDate(endDate) .build(); if(Build.VERSION.SDK_INT > Build.VERSION_CODES. JELLY_BEAN_MR2){ builder.setKeySize(keySize); } KeyPairGenerator generator = KeyPairGenerator. getInstance( "RSA", "AndroidKeyStore"); generator.initialize(spec); KeyPair keyPair= generator.generateKeyPair(); Initialize generator with your key parameters
  97. KeyPairGeneratorSpec 500Principal subject = ...; KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)

    .setAlias(alias) .setSerialNumber(serialNumber) .setSubject(subject) .setStartDate(startDate) .setEndDate(endDate) .build(); if(Build.VERSION.SDK_INT > Build.VERSION_CODES. JELLY_BEAN_MR2){ builder.setKeySize(keySize); } KeyPairGenerator generator = KeyPairGenerator. getInstance( "RSA", "AndroidKeyStore"); generator.initialize(spec); KeyPair keyPair= generator.generateKeyPair(); Creates and Saves new to to Android KeyStore
  98. KeyPairGeneratorSpec 500Principal subject = ...; KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)

    .setAlias(alias) .setSerialNumber(serialNumber) .setSubject(subject) .setStartDate(startDate) .setEndDate(endDate) .build(); if(Build.VERSION.SDK_INT > Build.VERSION_CODES. JELLY_BEAN_MR2){ builder.setKeySize(keySize); } KeyPairGenerator generator = KeyPairGenerator. getInstance( "RSA", "AndroidKeyStore" ); generator.initialize(spec); KeyPair keyPair= generator.generateKeyPair();
  99. KeyGenParameterSpec, Asymmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder(alias, purposes) .setKeySize(keySize) .setCertificateSerialNumber(serialNumber) .setCertificateSubject(subject) .setCertificateNotBefore(startDate) .setCertificateNotAfter(endDate) .setBlockModes("ECB") .setEncryptionPaddings( "PKCS1Padding"); KeyPairGeneratorSpec spec = builder.build();
  100. KeyGenParameterSpec, Asymmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder( alias, purposes) .setKeySize(keySize) .setCertificateSerialNumber(serialNumber) .setCertificateSubject(subject) .setCertificateNotBefore(startDate) .setCertificateNotAfter(endDate) .setBlockModes("ECB") .setEncryptionPaddings("PKCS1Padding"); KeyPairGeneratorSpec spec = builder.build(); You will be able to use generated key only for those purposes
  101. KeyGenParameterSpec, Asymmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder(alias, purposes) .setKeySize(keySize) .setCertificateSerialNumber(serialNumber) .setCertificateSubject(subject) .setCertificateNotBefore(startDate) .setCertificateNotAfter(endDate) .setBlockModes("ECB") .setEncryptionPaddings( "PKCS1Padding"); KeyPairGeneratorSpec spec = builder.build(); Use it to initialize KeyPairGenerator Mode and Padding will be required with Cipher
  102. KeyGenParameterSpec, Symmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder( alias, purposes) .setKeySize(keySize) .setBlockModes("CBC") .setEncryptionPaddings( "PKCS7Padding"); KeyPairGeneratorSpec spec = builder.build(); KeyGenerator gen = KeyGenerator. getInstance("AES","AndroidKeyStore"); gen.init(spec); SecretKey key = gen.generateKey();
  103. KeyGenParameterSpec, Symmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder(alias, purposes) .setKeySize(keySize) .setBlockModes("CBC") .setEncryptionPaddings("PKCS7Padding"); KeyPairGeneratorSpec spec = builder.build(); KeyGenerator gen = KeyGenerator. getInstance("AES","AndroidKeyStore"); gen.init(spec); SecretKey key = gen.generateKey();
  104. KeyGenParameterSpec, Symmetric int purposes = KeyProperties. PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT; Builder

    builder = new KeyGenParameterSpec.Builder(alias, purposes) .setKeySize(keySize) .setBlockModes("CBC") .setEncryptionPaddings( "PKCS7Padding"); KeyPairGeneratorSpec spec = builder.build(); KeyGenerator gen = KeyGenerator. getInstance("AES","AndroidKeyStore"); gen.init(spec); SecretKey key = gen.generateKey();
  105. Symmetric Cipher Requires to provide IV Specification by default KeyGenParameterSpec.Builder.setRandomizedEncryptionRequired()

    Sets whether encryption using this key must be sufficiently randomized to produce different ciphertexts for the same plaintext every time. Crashes with IV Spec required exception even if it is set to false
  106. Symmetric Cipher Requires to provide IV Specification by default KeyGenParameterSpec.Builder.setRandomizedEncryptionRequired()

    Sets whether encryption using this key must be sufficiently randomized to produce different ciphertexts for the same plaintext every time. Crashes with IV Spec required exception even if it is set to false
  107. Symmetric Cipher Requires to provide IV Specification by default KeyGenParameterSpec.Builder.setRandomizedEncryptionRequired()

    Sets whether encryption using this key must be sufficiently randomized to produce different ciphertexts for the same plaintext every time. Crashes with IV Spec required exception even if it is set to false
  108. Symmetric Encryption static final String IV_SEPARATOR = "]"; Cipher cipher

    = Cipher. getInstance("AES/CBC/PKCS7Padding" ); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getIV(); String ivString = Base64. encodeToString(iv, Base64.DEFAULT); String result = ivString + IV_SEPARATOR; ... result += cipherText;
  109. Symmetric Encryption static final String IV_SEPARATOR = "]"; Cipher cipher

    = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getIV(); String ivString = Base64. encodeToString(iv, Base64.DEFAULT); String result = ivString + IV_SEPARATOR; ... result += cipherText; Use automatically generated IV
  110. Symmetric Encryption static final String IV_SEPARATOR = "]"; Cipher cipher

    = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getIV(); String ivString = Base64. encodeToString(iv, Base64.DEFAULT); String result = ivString + IV_SEPARATOR; ... result += cipherText; Used to separe IV and ciphertext
  111. Symmetric Encryption static final String IV_SEPARATOR = "]"; Cipher cipher

    = Cipher. getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getIV(); String ivString = Base64. encodeToString(iv, Base64.DEFAULT); String result = ivString + IV_SEPARATOR; ... result += cipherText; Add IV to resulting ciphertext
  112. Symmetric Decryption Cipher cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); String[] split =

    data.split( IV_SEPARATOR); String ivString = split [0]; cipherText= split[1]; IvParameterSpec ivSpec = new IvParameterSpec(Base64. decode(ivString, Base64.DEFAULT)); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); ... Parse ciphertext and IV
  113. Symmetric Decryption Cipher cipher = Cipher. getInstance("AES/CBC/PKCS7Padding"); String[] split =

    data.split( IV_SEPARATOR); String ivString = split[0]; cipherText= split[1]; IvParameterSpec ivSpec = new IvParameterSpec(Base64. decode(ivString, Base64.DEFAULT)); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); ... Initialize cipher with IV
  114. Symmetric Decryption Cipher cipher = Cipher. getInstance("AES/CBC/PKCS7Padding" ); String[] split

    = data.split( IV_SEPARATOR); String ivString = split [0]; cipherText= split[1]; IvParameterSpec ivSpec = new IvParameterSpec(Base64. decode(ivString, Base64.DEFAULT)); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); ...
  115. Encrypt large data with RSA You can proceed as large

    data as key size specified for a RSA Key There are two options of how to do that 1. Create additional symmetric key. Encrypt your data with it. Then encrypt it with your public RSA key. Add encrypted key to encrypted data (the same way as we did with IV spec for example) 2. Use buffer to separate your data to chunks. And then proceed each chunk separately with RSA key. In the end merge chunks.
  116. Encrypt large data with RSA You can proceed as large

    data as key size specified for a RSA Key There are two options of how to do that 1. Create additional symmetric key. Encrypt your data with it. Then encrypt it with your public RSA key. Add encrypted key to encrypted data (the same way as we did with IV spec for example) 2. Use buffer to separate your data to chunks. And then proceed each chunk separately with RSA key. In the end merge chunks.
  117. Encrypt large data with RSA You can proceed as large

    data as key size specified for a RSA Key There are two options of how to do that 1. Create additional symmetric key. Encrypt your data with it. Then encrypt it with your public RSA key. Add encrypted key to encrypted data (the same way as we did with IV spec for example) 2. Use buffer to separate your data to chunks. And then proceed each chunk separately with RSA key. In the end merge chunks.
  118. Encrypt large data with RSA You can proceed as large

    data as key size specified for a RSA Key There are two options of how to do that 1. Create additional symmetric key. Encrypt your data with it. Then encrypt it with your public RSA key. Add encrypted key to encrypted data (the same way as we did with IV spec for example) 2. Use buffer to separate your data to chunks. And then proceed each chunk separately with RSA key. In the end merge chunks.
  119. KeyStore KeyStore keyStore = KeyStore. getInstance("AndroidKeyStore"); keyStore.load(null); // asymmetric key

    PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null); PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey(); // symmetric key SecretKey secretKey= (SecretKey) keyStore.getKey(alias, null); // delete key keyStore.deleteEntry(alias); // check if key exists boolean result = keyStore.isKeyEntry(alias); Don’t forget to set provider Just call load like this
  120. KeyStore KeyStore keyStore = KeyStore. getInstance("AndroidKeyStore"); keyStore.load(null); // asymmetric key

    PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null); PublicKey publicKey = keyStore.getCertificate(alias).getPublicKey(); // symmetric key SecretKey secretKey= (SecretKey) keyStore.getKey(alias, null); // delete key keyStore.deleteEntry(alias); // check if key exists boolean result = keyStore.isKeyEntry(alias);
  121. API Manage asymmetric and symmetric keys Cipher encryption and decryption

    RSA buffered encryption/decryption implementation Backward compatible
  122. API Manage asymmetric and symmetric keys Cipher encryption and decryption

    RSA buffered encryption/decryption implementation Backward compatible
  123. API Manage asymmetric and symmetric keys Cipher encryption and decryption

    RSA buffered encryption/decryption implementation Backward compatible
  124. API Manage asymmetric and symmetric keys Cipher encryption and decryption

    RSA buffered encryption/decryption implementation Backward compatible
  125. Compatibility Asymmetric keys On devices with API < 18, creates

    keystore file in local application cache. On devices with API >= 18, uses Android Keystore. Symmetric keys On devices with API < 23, creates keystore file in local application cache. On devices with API >= 18, uses Android Keystore.
  126. Compatibility Asymmetric keys On devices with API < 18, creates

    keystore file in local application cache. On devices with API >= 18, uses Android Keystore. Symmetric keys On devices with API < 23, creates keystore file in local application cache. On devices with API >= 18, uses Android Keystore.
  127. Example String alias = ...; char[] password = ...; //

    Create and save symmetric key Security.Store store = new Security.Store(getApplicationContext()); if (!store.hasKey(alias)) { SecretKey key = store.generateSymmetricKey(alias, password); } // Create and save asymmetric key KeyPair keyPair = store.generateAsymmetricKey(alias, password);
  128. Example String alias = ...; char[] password = ...; //

    Create and save symmetric key Security.Store store = new Security.Store(getApplicationContext()); if (!store.hasKey(alias)) { SecretKey key = store.generateSymmetricKey(alias, password); } // Create and save asymmetric key KeyPair keyPair = store.generateAsymmetricKey(alias, password); Create and saves 256-bit AES key
  129. Example String alias = ...; char[] password = ...; //

    Create and save symmetric key Security.Store store = new Security.Store(getApplicationContext()); if (!store.hasKey(alias)) { SecretKey key = store.generateSymmetricKey(alias, password); } // Create and save asymmetric key KeyPair keyPair = store.generateAsymmetricKey(alias, password); Create and saves 1024-bit RSA key
  130. Example // Get symmetric key SecretKey key = store.getSymmetricKey(alias, password);

    // Encrypt/Decrypt data Security.Crypto crypto = new Security.Crypto(Security. TRANSFORMATION_SYMMETRIC); String text = "Sample text"; String encryptedData = crypto.encrypt(text, key); Log.i("Security", "Encrypted data: " + encryptedData); String decryptedData = crypto.decrypt(encryptedData, key); Log.i("Security", "Decrypted data: " + decryptedData);
  131. Extended Usage KeyProps keyProps = new KeyProps.Builder() .setAlias(alias) .setPassword(password) .setKeySize(keysize)

    .setKeyType("RSA") .setSerialNumber(BigInteger. ONE) .setSubject(subject) .setStartDate(startDate) .setEndDate(end.Date) .setBlockModes("ECB") .setEncryptionPaddings( "PKCS1Padding") .setSignatureAlgorithm( "SHA256WithRSAEncryption" ) .build(); KeyPair keyPair = store.generateAsymmetricKey( keyProps);
  132. Extended Usage // as specified for RSA/ECB/PKCS1Padding keys final int

    encryptionBlockSize = keysize / 8 - 11; final int decryptionBlockSize = keysize / 8; Security.Crypto crypto = new Security.Crypto( "RSA/ECB/PKCS1Padding" , encryptionBlockSize, decryptionBlockSize); String text = "Some very long text"; String encryptedData = crypto.encrypt(text, key, false); String decryptedData = crypto.decrypt(encryptedData, key, false);
  133. Extended Usage // as specified for RSA/ECB/PKCS1Padding keys final int

    encryptionBlockSize = keysize / 8 - 11; final int decryptionBlockSize = keysize / 8; Security.Crypto crypto = new Security.Crypto( "RSA/ECB/PKCS1Padding", encryptionBlockSize, decryptionBlockSize); String text = "Some very long text"; String encryptedData = crypto.encrypt(text, key, false); String decryptedData = crypto.decrypt(encryptedData, key, false); Used for RSA buffering
  134. Extended Usage // as specified for RSA/ECB/PKCS1Padding keys final int

    encryptionBlockSize = keysize / 8 - 11; final int decryptionBlockSize = keysize / 8; Security.Crypto crypto = new Security.Crypto( "RSA/ECB/PKCS1Padding", encryptionBlockSize, decryptionBlockSize); String text = "Some very long text"; String encryptedData = crypto.encrypt(text, key, false); String decryptedData = crypto.decrypt(encryptedData, key, false); Whenever to use IV
  135. Nikolay Elenkov, Book Android Security Internals: An In-Depth Guide to

    Android's Security Architecture Nikolay Elenkov, Blog http://nelenkov.blogspot.com/