Encryption ================================================================================ .. only:: html .. contents:: Index :local: .. _EncryptionOverview: Overview -------------------------------------------------------------------------------- Encryption is required for confidential information like personal data, passwords etc in the following cases. * Sending/receiving confidential information through a network medium like Internet * Storing confidential information in external resources like database, file etc | Spring Security also offers encryption related functions besides the major functions like "Authentication" and "Authorization". | However, since functions offered by Spring Security are limited, the encryption methods which are not supported by Spring Security must be implemented independently. The guideline explains following processes. * Encryption and decryption by common key encryption methods which use class offered by Spring Security * Generation of pseudo-random numbers which use class offered by Spring Security * Encryption and decryption by public key encryption method which use JCA (Java Cryptography Architecture) * Encryption and decryption by hybrid encryption method which use JCA For details of Encryption function of Spring Security, refer \ `Spring Security Reference -Spring Security Crypto Module- `_\ . .. _EncryptionOverviewEncryptionScheme: Encryption method ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Encryption method is explained below. Common key encryption method """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | It is a method which uses the same key during encryption and decryption. | Since the method shares a key used in decryption for the encryption, a different path to safely transfer the key to encryption side is required. Public key encryption method """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | It is a method wherein encryption is performed by using a public key offered by decryption side and decryption is performed by using a secret key which is paired with the public key.\ | Secret key used while decrypting encrypted text is not published resulting in high security strength, however cost of encryption and decryption is likely to be high. Hybrid encryption method """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | It is a method which combines merits of common key encryption method wherein processing cost is less and merits of public key encryption method wherein security strength is high due to easy management and distribution of key. | This method is used in SSL/TLS etc. For example, in HTTPS communication, common key generated at the client side is sent after encrypting it with public key on the server side and common key is decrypted at the server by using secret key paired with public key. The subsequent communication is done by a common key encryption method which uses a shared common key. This method consists of * Confidential information which is likely to be large in size is encrypted by a common key encryption method wherein the processing cost is less * A common key with smaller size wherein safe distribution is required is encrypted by using a public key encryption method with high security strength Since common key used while decrypting confidential information is protected by secret key, security strength of public key encryption method is retained while achieving a high-speed encryption and decryption process than public key encryption method. Process flow of hybrid encryption method from encryption to decryption is shown in the following figure.. .. figure:: ./images_Encryption/EncryptionHybrid.png :alt: Hybrid Encryption :width: 100% 1. Sender generates a common key for encryption of plain text. 2. Plain text is encrypted by common key generated by sender. 3. Sender uses public key of receiving side to encrypt common key. 4. Sender sends encrypted text along with encrypted common key. 5. Receiving side decrypts encrypted common key by using secret key on receiving side. 6. Receiving side decrypts encrypted text by decrypted common key | .. _EncryptionOverviewEncryptionAlgorithm: Encryption algorithm ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Encryption algorithm is explained. DES / 3DES """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | DES (Data Encryption Standard) is an algorithm standardised in USA as an algorithm for common encryption method. Currently, it is not recommended since key length is short at 56 bits. | 3DES (triple DES) is an encryption algorithm which repeats DES while changing the key. .. _EncryptionOverviewEncryptionAlgorithmAes: AES """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | AES (Advanced Encryption Standard) is an algorithm for common key encryption method. It is an encryption standard established subsequent to DES and is used as a current default standard for encryption. | Also, ECB (Electronic Codebook), CBC (Cipher Block Chaining) and OFB (Output Feedback) are provided as encryption mode wherein a message longer than the block length is encrypted. Of these, CBC is widely used. .. note:: **AES with GCM** GCM (Galois/Counter Mode) is an encryption mode generally accepted for feasible parallel processing and excellent processing efficiency as compared to CEC and can be used in AES. RSA """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | RSA is an algorithm of public key encryption method. Ability of a computing machine impacts the algorithm since it is based on difficulty of prime numbers factoring. It requires adequate key length as indicated in "Issues of encryption algorithm in 2010". At present, 2048 bits is used a standard length. DSA / ECDSA """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | DSA (Digital Signature Algorithm) is a standard specification for digital signature. It is based on the difficulty of discrete logarithmic problem. | ECDSA (Elliptic Curve Digital Signature Algorithm ) is a variant of DSA which uses Elliptic curve photography. Elliptic curve photography offers an advantage of reducing key length which is necessary for maintaining security level. .. _EncryptionOverviewPseudoRandomNumber: Pseudo-random number (Generator) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Random numbers are used in the generation of a key. | In this case, if the value of a number generated at random can be predicted, encryption security can no longer be maintained. Hence, a random number which cannot be predicted easily (pseudo-random number) must be used. | It is a pseudo-random number generator which is used to generate a pseudo-random number. .. _EncryptionOverviewCipher: javax.crypto.Cipher class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | \ ``Cipher``\ class offers encryption and decryption functions, and specifies a combination of encryption algorithms like AES or RSA, encryption modes like ECB or CBC and padding methods like PKCS1. | | Encryption mode is a mechanism to encrypt messages longer than block length, as explained in \ :ref:`EncryptionOverviewEncryptionAlgorithmAes`\ . | Also, padding method is a method of storage when encryption target that does not meet the required block length is to be encrypted. | | Java application specifies a combination in the \ ``//``\ or \ ````\ format. For example, \ ``AES/CBC/PKCS5Padding``\ or \ ``RSA``\ are used. For details, refer to \ `JavaDoc of Cipher class `_\ . .. _EncryptionOverviewSpringSecurity: Encryption function in Spring Security ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Spring Security offers an encryption and decryption function which uses a common key encryption method. | Encryption algorithm is 256-bit AES using PKCS #5's PBKDF2 (Password-Based Key Derivation Function #2). | Encryption mode is CBC and padding method is PKCS5Padding. Components for encryption and decryption """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Spring Security offers following interfaces as a function for encryption and decryption using common key encryption method. * \ ``org.springframework.security.crypto.encrypt.TextEncryptor``\ (For text) * \ ``org.springframework.security.crypto.encrypt.BytesEncryptor``\ (For byte array) Also, following classes are offered as implementation classes for these interfaces and \ ``Cipher``\ class is used internally. * \ ``org.springframework.security.crypto.encrypt.HexEncodingTextEncryptor``\ (For text) * \ ``org.springframework.security.crypto.encrypt.AesBytesEncryptor``\ (For byte array) Components to generate random numbers """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Spring Security offers following interfaces as functions to generate random numbers (key). * \ ``org.springframework.security.crypto.keygen.StringKeyGenerator``\ (for text) * \ ``org.springframework.security.crypto.keygen.BytesKeyGenerator``\ (for byte array) Also, following classes are offered as implementation classes for these interfaces. * \ ``org.springframework.security.crypto.keygen.HexEncodingStringKeyGenerator``\ (for text) * \ ``org.springframework.security.crypto.keygen.SecureRandomBytesKeyGenerator``\ (for byte array. Generate a different key length by \ ``generateKey``\ method and return) * \ ``org.springframework.security.crypto.keygen.SharedKeyGenerator``\ (for byte array. Return same key length set by constructor, using \ ``generateKey``\ method) .. note:: **Spring Security RSA** \ `spring-security-rsa `_\ offers API for public key encryption method and hybrid encryption method which use RSA as an encryption algorithm. spring-security-rsa is currently not managed as \ official repository of Spring _\ . Later, how to use the repository will be explained in the guideline after moving it under official repository of Spring. spring-security-rsa offers 2 classes given below. * \ ``org.springframework.security.crypto.encrypt.RsaRawEncryptor``\ A class that offers encryption and decryption functions which use public key encryption method. * \ ``org.springframework.security.crypto.encrypt.RsaSecretEncryptor``\ A class that offers encryption and decryption functions which use hybrid encryption method. | .. _EncryptionHowToUse: How to use -------------------------------------------------------------------------------- An unlimited strength JCE jurisdiction policy file must be applied for handling key length 256 bits of AES in some Java products like Oracle. .. note:: **JCE jurisdiction policy file** Default encryption algorithm strength is restricted in some Java products due to relation with import regulations. If a more powerful algorithm is to be used, an unlimited strength JCE jurisdiction policy file must be obtained and installed in JDK/JRE. For details, refer \ `Java Cryptography Architecture Oracle Providers Documentation `_\ . Download destination for JCE jurisdiction policy file * \ `For Oracle Java 8 `_\ * \ `For Oracle Java 7 `_\ .. _EncryptionHowToUseCommonKey: Common key encryption method ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | A method is explained wherein AES is used as an encryption algorithm. Encryption of character string """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Encrypt text (string). .. code-block:: java public static String encryptText( String secret, String salt, String plainText) { TextEncryptor encryptor = Encryptors.text(secret, salt); // (1) return encryptor.encrypt(plainText); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#text``\ method by specifying common key and salt, and generate instance of \ ``TextEncryptor``\ class. | Since initialization vector of generated instance is random, a varied result is returned at the time of encryption. It should be noted that CEC is used as an encryption mode. | Common key and salt specified during encryption are also used at the time of decryption. * - | (2) - | Encrypt plain text by using \ ``encrypt``\ method. .. note:: **Regarding encryption results** Return value of \ ``encrypt``\ method (encryption results) return a different value for each execution, however, if key and salt are identical, decryption process results will be similar as well (can be correctly decrypted). | - Fetch identical encryption results. This method is used in the processes such as searching the database etc.using encrypted results. However, whether to use the method must be reviewed considering possible reduction in the security strength. .. code-block:: java public static void encryptTextResult( String secret, String salt, String plainText) { TextEncryptor encryptor = Encryptors.queryableText(secret, salt); // (1) System.out.println(encryptor.encrypt(plainText)); // (2) System.out.println(encryptor.encrypt(plainText)); // } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr.No. - Description * - | (1) - | When identical value must be fetched as encryption results, generate an instance of \ ``TextEncryptor``\ class by using \ ``Encryptors#queryableText``\ method. * - | (2) - | The instance generated by \ ``Encryptors#queryableText``\ method returns identical values as the encryption results for \ ``encrypt``\ method. | - Encrypt text (string) by using AES which uses GCM. AES using GCM can be used in Spring Security4.0.2 and subsequent versions. Processing efficiency is superior to CEC as explained in \ :ref:`EncryptionOverviewEncryptionAlgorithmAes`\ . .. code-block:: java public static String encryptTextByAesWithGcm(String secret, String salt, String plainText) { TextEncryptor aesTextEncryptor = Encryptors.delux(secret, salt); // (1) return aesTextEncryptor.encrypt(plainText); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#delux``\ method by specifying common key and salt, and generate an instance of \ ``TextEncryptor``\ class. | Common key and salt specified during encryption are also used at the time of decryption. * - | (2) - | Encrypt plain text by using \ ``encrypt``\ method. .. note:: **Java support for AES which uses GCM** AES using GCM can be used in Java SE8 and subsequent versions. For details, refer \ `JDK 8 security enhancement `_\ . | Decryption of string """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Decrypt encryption text of text (string). .. code-block:: java public static String decryptText(String secret, String salt, String cipherText) { TextEncryptor decryptor = Encryptors.text(secret, salt); // (1) return decryptor.decrypt(cipherText); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#text``\ method by specifying common key and salt, and generate an instance of \ ``TextEncryptor``\ class. | Specify values used at the time of encryption as common key and salt. * - | (2) - | Decrypt encrypted text by using \ ``decrypt``\ method. | - Decrypt encrypted text of text (string) by using AES which uses GCM. .. code-block:: java public static String decryptTextByAesWithGcm(String secret, String salt, String cipherText) { TextEncryptor aesTextEncryptor = Encryptors.delux(secret, salt); // (1) return aesTextEncryptor.decrypt(cipherText); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#delux``\ method by specifying common key and salt, and generate an instance of \ ``TextEncryptor``\ class. | Specify values at the time of encryption as common key and salt. * - | (2) - | Decrypt encrypted text by using \ ``decrypt``\ method. | Encryption of byte array """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Encrypt byte array. .. code-block:: java public static byte[] encryptBytes(String secret, String salt, byte[] plainBytes) { BytesEncryptor encryptor = Encryptors.standard(secret, salt); // (1) return encryptor.encrypt(plainBytes); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#standard``\ method by specifying common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. | Common key and salt specified during encryption are also used at the time of decryption. * - | (2) - | Encrypt plain text of byte array by using \ ``encrypt``\ method. | - Encrypt byte array by using AES which uses GCM. .. code-block:: java public static byte[] encryptBytesByAesWithGcm(String secret, String salt, byte[] plainBytes) { BytesEncryptor aesBytesEncryptor = Encryptors.stronger(secret, salt); // (1) return aesBytesEncryptor.encrypt(plainBytes); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#stronger``\ method by specifying common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. | Common key and salt specified during encryption are also used at the time of decryption. * - | (2) - | Encrypt plain text of byte array by using \ ``encrypt``\ method. | Decryption of byte array """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Decrypt encrypted text of byte array. .. code-block:: java public static byte[] decryptBytes(String secret, String salt, byte[] cipherBytes) { BytesEncryptor decryptor = Encryptors.standard(secret, salt); // (1) return decryptor.decrypt(cipherBytes); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#standard``\ method by specifying common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. | Specify values used at the time of encryption as common key and salt. * - | (2) - | Decrypt encrypted text of byte array by using \ ``decrypt``\ method. | - Decrypt byte array using AES which use GCM. .. code-block:: java public static byte[] decryptBytesByAesWithGcm(String secret, String salt, byte[] cipherBytes) { BytesEncryptor aesBytesEncryptor = Encryptors.stronger(secret, salt); // (1) return aesBytesEncryptor.decrypt(cipherBytes); // (2) } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``Encryptors#stronger``\ method by specifying common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. | Specify values used at the time of encryption as common key and salt. * - | (2) - | Decrypt encrypted text of byte array by using \ ``decrypt``\ method. | .. _EncryptionHowToUsePublicKey: Public key encryption method ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Since functions related to public key encryption method are not offered by Spring Security, a method which uses JCA and OpenSSL is explained using a sample code. Preliminary preparation (Generation of key pairs using JCA) """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Generate key pairs (a combination of public key / secret key) using JCA, perform encryption and decryption process by using public key and secret key respectively. .. code-block:: java public void generateKeysByJCA() { try { KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); // (1) generator.initialize(2048); // (2) KeyPair keyPair = generator.generateKeyPair(); // (3) PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); byte[] cipherBytes = encryptByPublicKey("Hello World!", publicKey); // (4) String plainText = decryptByPrivateKey(cipherBytes, privateKey); // (5) System.out.println(plainText); } catch (NoSuchAlgorithmException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Specify RSA algorithm and generate an instance of \ ``KeyPairGenerator``\ class. * - | (2) - | Specify 2048 bits as a key length. * - | (3) - | Generate key pairs. * - | (4) - | Use public key and perform encryption process. Processing details will be described later. * - | (5) - | Use secret key and perform decryption process. Processing details will be described later. .. note:: **When the encrypted data is to be handled as string** When encrypted data is to be handled as string like in external system linkage etc, Base64 encoding can be listed as one of the measures. \ ``java.util.Base64``\ of Java standard is used in case of subsequent versions of Java SE8. In the earlier versions, \ ``org.springframework.security.crypto.codec.Base64``\ of Spring Security is used. A method used for Base64 encoding and decoding is explained using \ ``java.util.Base64``\ of Java standard. * Base64 encoding .. code-block:: java // omitted byte[] cipherBytes = encryptByPublicKey("Hello World!", publicKey); // Encryption process String cipherString = Base64.getEncoder().encodeToString(cipherBytes); // Convert encrypted text of byte array to string // omitted * Base64 decoding .. code-block:: java // omitted byte[] cipherBytes = Base64.getDecoder().decode(cipherString); // Convert encrypted text of string to byte array String plainText = decryptByPrivateKey(cipherBytes, privateKey); // Decryption process // omitted | Encryption """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Use public key and encrypt character string. .. code-block:: java public byte[] encryptByPublicKey(String plainText, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // (1) cipher.init(Cipher.ENCRYPT_MODE, publicKey); // (2) return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8)); // } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr.No. - Description * - | (1) - | Specify encryption algorithm, encryption mode and padding method, and generate an instance of \ ``Cipher``\ class. * - | (2) - | Execute encryption process. | Decryption """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Use secret key and decrypt byte array. .. code-block:: java public String decryptByPrivateKey(byte[] cipherBytes, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // (1) cipher.init(Cipher.DECRYPT_MODE, privateKey); // (2) byte[] plainBytes = cipher.doFinal(cipherBytes); // return new String(plainBytes, StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Specify encryption algorithm, encryption mode and padding method, and generate an instance of \ ``Cipher``\ class. * - | (2) - | Execute decryption process. | OpenSSL """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" | If Cipher is identical, a different method can be used for encryption and decryption for public key encryption method. | Here, key pairs are created in advance by using OpenSSL and encryption is performed by JCA, by using this public key. Hence, a method wherein decryption process is performed by OpenSSL, by using the secret key is explained. .. note:: **OpenSSL** The software must be installed for creating key pairs by OpenSSL. It can be downloaded from the following site. Download destination for OpenSSL * \ `For Linux `_\ * \ `For Windows `_\ | - Create key pairs by OpenSSL as a preliminary preparation. .. code-block:: console $ openssl genrsa -out private.pem 2048 # (1) $ openssl pkcs8 -topk8 -nocrypt -in private.pem -out private.pk8 -outform DER # (2) $ openssl rsa -pubout -in private.pem -out public.der -outform DER # (3) .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Generate secret key of 2048 bits (DER format) by OpenSSL.. * - | (2) - | Convert secret key to PKCS#8 format for reading it from Java application. * - | (3) - | Generate public key (DER format) from secret key. | - Read public key created by OpenSSL in the application and perform encryption process by using public key that has been read. .. code-block:: java public void useOpenSSLDecryption() { try { KeySpec publicKeySpec = new X509EncodedKeySpec( Files.readAllBytes(Paths.get("public.der"))); // (1) KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); // (2) byte[] cipherBytes = encryptByPublicKey("Hello World!", publicKey); // (3) Files.write(Paths.get("encryptedByJCA.txt"), cipherBytes); System.out.println("Please execute the following command:"); System.out .println("openssl rsautl -decrypt -inkey hoge.pem -in encryptedByJCA.txt"); } catch (IOException e) { throw new SystemException("e.xx.xx.9001", "input/output error.", e); } catch (NoSuchAlgorithmException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeySpecException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr.No. - Description * - | (1) - | Read binary data from public key file. * - | (2) - | Generate an instance of \ ``PublicKey``\ class from binary data. * - | (3) - | Perform encryption process by using public key. | - Check that details encrypted by JCA can be decrypted by OpenSSL. .. code-block:: console $ openssl rsautl -decrypt -inkey private.pem -in encryptedByJCA.txt # (1) .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Decrypt by OpenSSL by using a secret key. | | Further, a method wherein encryption and decryption are performed by OpenSSL and JCA respectively using key pairs created by OpenSSL is explained. - Perform encryption process by using OpenSSL commands. .. code-block:: console $ echo Hello | openssl rsautl -encrypt -keyform DER -pubin -inkey public.der -out encryptedByOpenSSL.txt # (1) .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Encrypt by OpenSSL by using a public key. | - Read secret key created by OpenSSL in the application and perform decryption process by using a secret key that has been read. .. code-block:: java public void useOpenSSLEncryption() { try { KeySpec privateKeySpec = new PKCS8EncodedKeySpec( Files.readAllBytes(Paths.get("private.pk8"))); // (1) KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); // (2) String plainText = decryptByPrivateKey( Files.readAllBytes(Paths.get("encryptedByOpenSSL.txt")), privateKey); // (3) System.out.println(plainText); } catch (IOException e) { throw new SystemException("e.xx.xx.9001", "input/output error.", e); } catch (NoSuchAlgorithmException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeySpecException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Read binary data from secret key file of PKCS #8 format and generate an instance of \ ``PKCS8EncodedKeySpec``\ class. * - | (2) - | Generate an instance of \ ``PrivateKey``\ class from \ ``KeyFactory``\ class. * - | (3) - | Perform decryption process by using a secret key. | .. _EncryptionHowToUseHybrid: Hybrid encryption method ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | Similar to public key encryption method, since functions related to hybrid encryption methods are not offered by Spring Security, it is explained using a sample code. | The sample code refers to \ `RsaSecretEncryptor class `_\ of spring-security-rsa. Encryption """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: java public byte[] encrypt(byte[] plainBytes, PublicKey publicKey, String salt) { byte[] random = KeyGenerators.secureRandom(32).generateKey(); // (1) BytesEncryptor aes = Encryptors.standard( new String(Hex.encode(random)), salt); // (2) try (ByteArrayOutputStream result = new ByteArrayOutputStream()) { final Cipher cipher = Cipher.getInstance("RSA"); // (3) cipher.init(Cipher.ENCRYPT_MODE, publicKey); // (4) byte[] secret = cipher.doFinal(random); // (5) byte[] data = new byte[2]; // (6) data[0] = (byte) ((secret.length >> 8) & 0xFF); // data[1] = (byte) (secret.length & 0xFF); // result.write(data); // result.write(secret); // (7) result.write(aes.encrypt(plainBytes)); // (8) return result.toByteArray(); // (9) } catch (IOException e) { throw new SystemException("e.xx.xx.9001", "input/output error.", e); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``KeyGenerators#secureRandom``\ method by specifyinh 32 bytes as a key length and generate an instance of \ ``BytesKeyGenerator``\ class. | Call \ ``BytesKeyGenerator#generateKey``\ method and generate a common key. | For details, refer to \ :ref:`EncryptionHowToUsePseudoRandomNumber`\ . * - | (2) - | Specify generated common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. * - | (3) - | specify RSA as an encryption algorithm and generate an instance of \ ``Cipher``\ class. * - | (4) - | Specify encryption mode constant and public key, and initialise an instance of \ ``Cipher``\ class. * - | (5) - | Execute encryption process of common key. The encryption is performed by using public key encryption process. * - | (6) - | Store length of encrypted common key in encrypted text of byte array. Length of stored common key is used at the time of decryption. * - | (7) - | Store encrypted common key in encrypted text of byte array. * - | (8) - | Encrypt plain text and store in encrypted text of byte array. The encryption is performed by using common key encryption process. * - | (9) - | Return encrypted text of byte array. | Decryption """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: java public byte[] decrypt(byte[] cipherBytes, PrivateKey privateKey, String salt) { try (ByteArrayInputStream input = new ByteArrayInputStream(cipherBytes); ByteArrayOutputStream output = new ByteArrayOutputStream()) { byte[] b = new byte[2]; // (1) input.read(b); // int length = ((b[0] & 0xFF) << 8) | (b[1] & 0xFF); // byte[] random = new byte[length]; // (2) input.read(random); // final Cipher cipher = Cipher.getInstance("RSA"); // (3) cipher.init(Cipher.DECRYPT_MODE, privateKey); // (4) String secret = new String(Hex.encode(cipher.doFinal(random))); // (5) byte[] buffer = new byte[cipherBytes.length - random.length - 2]; // (6) input.read(buffer); // BytesEncryptor aes = Encryptors.standard(secret, salt); // (7) output.write(aes.decrypt(buffer)); // (8) return output.toByteArray(); // (9) } catch (IOException e) { throw new SystemException("e.xx.xx.9001", "input/output error.", e); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new SystemException("e.xx.xx.9002", "No Such setting error.", e); } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new SystemException("e.xx.xx.9003", "Invalid setting error.", e); } } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Fetch length of encrypted common key. * - | (2) - | Fetch encrypted common key. * - | (3) - | Specify RSA as an encryption algorithm and generate an instance of \ ``Cipher``\ class. * - | (4) - | Specify decryption mode constant and secret key, and initialise an instance of \ ``Cipher``\ class. * - | (5) - | Execute decryption process of common key. Decryption is performed by using public key encryption process. * - | (6) - | Fetch decryption target. * - | (7) - | Specify decrypted common key and salt, and generate an instance of \ ``BytesEncryptor``\ class. * - | (8) - | Execute decryption process. Decryption is performed by using common key encryption process. * - | (9) - | Return plain text of decrypted byte array. | .. _EncryptionHowToUsePseudoRandomNumber: Random number generation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Generation of string type pseudo-random number """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: java public static void createStringKey() { StringKeyGenerator generator = KeyGenerators.string(); // (1) System.out.println(generator.generateKey()); // (2) System.out.println(generator.generateKey()); // } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Generate an instance of key (pseudo-random number) generator \ ``StringKeyGenerator``\ class. | If key is generated by this generator, a different value is obtained for each instance. | | Key length cannot be specified, a key of length 8 byte is always generated. * - | (2) - | Generate a key (pseudo-random number) by using \ ``generateKey``\ method. | Generation of byte array type pseudo-randon number """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - Generate a different key. .. code-block:: java public static void createDifferentBytesKey() { BytesKeyGenerator generator = KeyGenerators.secureRandom(); // (1) System.out.println(Arrays.toString(generator.generateKey())); // (2) System.out.println(Arrays.toString(generator.generateKey())); // } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Call \ ``KeyGenerators#secureRandom``\ method and generate an instance of key (pseudo-random number) generator \ ``BytesKeyGenerator``\ class. | If key is generated by this generator, a different value is obtained for each instance. | | When key length is not specified, a key of length - 8 bytes is generated by default. * - | (2) - | Generate a key by using \ ``generateKey``\ method. | - Generate identical key. .. code-block:: java public static void createSameBytesKey() { BytesKeyGenerator generator = KeyGenerators.shared(32); // (1) System.out.println(Arrays.toString(generator.generateKey())); // (2) System.out.println(Arrays.toString(generator.generateKey())); // } .. tabularcolumns:: |p{0.10\linewidth}|p{0.90\linewidth}| .. list-table:: :header-rows: 1 :widths: 10 90 * - Sr. No. - Description * - | (1) - | Specify 32 bytes as key length, call \ ``KeyGenerators#shared``\ method and generate an instance of key (pseudo-random number) generator \ ``BytesKeyGenerator``\ class. | If key is generated by this generator, same value is obtained for each instance. | | Specifying key length is mandatory. * - | (2) - | Generate key by using \ ``generateKey``\ method. | .. raw:: latex \newpage