Hello,
Through several articles, I would like present the cryptographic mechanisms, types of keys, certificate, types of algorithms …etc:
- PRESENTATION : Concepts of Cryptography (concepts, types of keys symmetric/asymmetric, …)
- The principles of SSL
- The principles of Signature and Certificate
- The principles of Hardware Security Module HSM
- Encoding with base64, base64url, rfc-4648
- Encryption with Blowfish (Anonymization)
- Encryption with AES/CBC, AES/EBC (Encryption of files)
- Encryption with PBEWithMD5AndDES (Encryption of files)
- Encryption with RSA (asymmetric keys private and public)
- KeyStore, JCEKS, SecretKey, PrivateKey, PublicKey, Certificate
- Example, Use of SecretKey, PrivateKey, PublicKey, CSV file (CryptoTools, GenericObfuscationFile)
Encryption with RSA (asymmetric keys private and public)
- Presentation
RSA is an asymmetric cryptography algorithm, widely used in electronic commerce, and more generally to exchange confidential data on the Internet. This algorithm was described in 1977 by Ronald Rivest, Adi Shamir and Leonard Adleman. RSA was patented by the Massachusetts Institute of Technology (MIT) in 1983 in the United States. The patent expired on 21 September 2000.The RSA encryption uses a pair of keys (integers) composed of a public key to encrypt and a private key to decrypt confidential data. RSA is based on the difficulty of factorizing large numbers, and the one-way function used is a “power” function.
The keys (public, private) keys are built via the following steps:
1.Choose two distinct primes numbers : p and q
2.Calculate the multiplication of this two numbers : n = p * q named encryption modulus
3.Calculate φ(n) = (p – 1) * (q -1) (Value of the Euler indicator in ñ)
4.Choose a natural integer e prime number with φ(n) and strictly lower to φ(n) : p,q < e < φn , pgcd(n,e) = 1, named encryption exponent
5. Calculate the natural integer d, reverse of e modulo φ(n), and strictly lower to φ(n) : p,q < d < φn , e*d mod n = 1 named decryption exposant.
These informations are accessible via the Java Object like sun.security.rsa.RSAPublicKeyImpl and sun.security.rsa.RSAPrivateCrtKeyImpl via the methods : getPublicExponent(), getPrimeExponentP(), getPrimeExponentQ(), getPrimeP(), getPrimeQ() …etc.
Important note : The RSA encryption has a limitation linked to key’s length. For example, in our case, the size of RSA key’s length being 1024 bits / 128 bytes (1024/8), the max length of data to encrypt will be 128 – 11 = 117 bytes. If the length of data to encrypt is superior to 117 bytes, the encryption is going to throw a “javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes”.
- Tools
As described in the post http://www.javablog.fr/javacrypto-encryption-list-providers-and-algo.html, we could find the available algorithm, tools (cipher, generator) in each reachable provider. In our case, we use the SunJCE Provider which is enough (http://javasearch.developpez.com/sun/j2se/1.6.0/technotes/guides/security/SunProviders.html#SunJCEProvider)
The following algorithms are available in the SunJCE provider:
[2] SunRsaSign v1.5: Sun RSA signature provider
- KeyFactory.RSA -> sun.security.rsa.RSAKeyFactory
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
- KeyPairGenerator.RSA -> sun.security.rsa.RSAKeyPairGenerator
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
[3] SunJSSE v1.6: Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)
- KeyFactory.RSA -> sun.security.rsa.RSAKeyFactory
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
- KeyPairGenerator.RSA -> sun.security.rsa.RSAKeyPairGenerator
aliases: [1.2.840.113549.1.1, OID.1.2.840.113549.1.1]
[4] SunJCE v1.6: SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)
- Cipher.RSA -> com.sun.crypto.provider.RSACipher
attributes: {SupportedKeyClasses=java.security.interfaces.RSAPublicKey|java.security.interfaces.RSAPrivateKey, SupportedPaddings=NOPADDING|PKCS1PADDING|OAEPWITHMD5ANDMGF1PADDING|OAEPWITHSHA1ANDMGF1PADDING|OAEPWITHSHA-1ANDMGF1PADDING|OAEPWITHSHA-256ANDMGF1PADDING|OAEPWITHSHA-384ANDMGF1PADDING|OAEPWITHSHA-512ANDMGF1PADDING, SupportedModes=ECB}
- KeyGenerator.SunTlsRsaPremasterSecret -> com.sun.crypto.provider.TlsRsaPremasterSecretGenerator
- Example : Encryption of data via the algorithm “RSA/ECB/PKCS1Padding” on 1024bits
… Code for the generation of public and private keys:KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(1024); KeyPair keyPair = keyGen.genKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate();
… some methods for encryption/ciphering with public key:
- via the byte value of public key,
- via the modulus and exponent elements of public key,
- via directly the public key,
public static byte[] encrypt(byte[] keyValue, byte[] data) throws Exception { // Constrution of PublicKey from byte[] KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(keyValue)); return encrypt(publicKey, data); } public static byte[] encrypt(BigInteger modpublic, BigInteger exppublic, byte[] data) throws Exception { // Constrution of PublicKey from modulus and Exponent RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modpublic, exppublic); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); return encrypt(publicKey, data); } public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception { Cipher c = Cipher.getInstance(ALGORITHM); c.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encVal = c.doFinal(data); return encVal; }
… some methods for decryption/deciphering with private key:- via the byte value of private key,
- via the the modulus and exponent elements of private key,
- via directly the private key,
public static byte[] decrypt(byte[] keyValue, byte[] encryptedData) throws Exception { // Constrution of PrivateKey from byte[] KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(keyValue)); return decrypt(privateKey, encryptedData); } public static byte[] decrypt(BigInteger modprivate, BigInteger expprivate, byte[] encryptedData) throws Exception { // Constrution of PrivateKey from modulus and Exponent RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modprivate, expprivate); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return decrypt(privateKey, encryptedData); } public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws Exception { Cipher c = Cipher.getInstance(ALGORITHM); c.init(Cipher.DECRYPT_MODE, privateKey); byte[] decValue = c.doFinal(encryptedData); return decValue; }
…here a TEST 1 of encryption/decryption with directly the public and private keys://Generation of keys PublicKey publicKey = ....; System.out.println("Public key =" + ((sun.security.rsa.RSAPublicKeyImpl)publicKey)); PrivateKey privateKey = ...; System.out.println("Private key =" + ((sun.security.rsa.RSAPrivateCrtKeyImpl)privateKey)); // Data String sourceData = "123456ds fds àçèé#&çer çer "+System.getProperty("line.separator")+" ^rrr 7897ezrz"; System.out.println("Original=" + sourceData); // Encrypt data byte[] encryptData = EncryptionRsaEcbPkcs1Padding.encrypt(publicKey, sourceData.getBytes()); System.out.println("Encoded=" + new String(encryptData)); // Decrypt data byte[] decryptData = EncryptionRsaEcbPkcs1Padding.decrypt(privateKey, encryptData); String finalData = (decryptData!=null)? new String(decryptData):""; System.out.println("Decoded=" + finalData); System.out.println("Decoded is equal to Original=" + (finalData.equals(sourceData)));
…here the outputs:
Public key =Sun RSA public key, 1024 bits
modulus: 108236464083379203986747740102294506670642332644595091140477437212401770341725043446331666439922563601662126192294403912678804313052165471480180527273763676015029833044710156310334154567843847063265648379340267370388318243580677624706287519462429736743486286443163528711213522234983714241340528082087997553997public exponent: 65537
Private key =sun.security.rsa.RSAPrivateCrtKeyImpl@a763dOriginal=123456ds fds àçèé#&çer çer
^rrr 7897ezrzEncoded=bU,DÝF¡üá?œì"±\+°-Rµ½™Ý¾CÞªhŽûS‹+©à1qlvE0Ô~áMm&À4éAÎŒ!œè,TWP»5ž[ïvù`ȧÂîøxa‚‡ƒáwÛÕ‰j{brûBŽ¹Ä¦•®¡wàfÂkE*Õ´êf1¥qB?ì®
Decoded=123456ds fds àçèé#&çer çer
^rrr 7897ezrzDecoded is equal to Original=true
…here a TEST 2 of encryption/decryption with the byte value of public and private keys://Generation of keys PublicKey publicKey = ....; System.out.println("Public key =" + ((sun.security.rsa.RSAPublicKeyImpl)publicKey)); PrivateKey privateKey = ...; System.out.println("Private key =" + ((sun.security.rsa.RSAPrivateCrtKeyImpl)privateKey)); // Data String sourceData = "123456ds fds àçèé#&çer çer "+System.getProperty("line.separator")+" ^rrr 7897ezrz"; System.out.println("Original=" + sourceData); // Encrypt data byte[] encryptData = EncryptionRsaEcbPkcs1Padding.encrypt(publicKey.getEncoded(), sourceData.getBytes()); System.out.println("Encoded=" + new String(encryptData)); // Decrypt data byte[] decryptData = EncryptionRsaEcbPkcs1Padding.decrypt(privateKey.getEncoded(), encryptData); String finalData = (decryptData!=null)? new String(decryptData):""; System.out.println("Decoded=" + finalData); System.out.println("Decoded is equal to Original=" + (finalData.equals(sourceData)));
…here the outputs:
Public key =Sun RSA public key, 1024 bits
modulus: 97392577533464847212159666283371265312195963457783867011563594880101035071664888285246165055268403437113791299196226113467171554262215338665624196367846941742826902988371223917394549714601526511256658364514894511973625205592508082767463020431470353350647479947777222505844148608989650023898960716372820993061
public exponent: 65537Private key =sun.security.rsa.RSAPrivateCrtKeyImpl@278ef
Original=123456ds fds àçèé#&çer çer
^rrr 7897ezrzEncoded=¤jðЯ‘Å_Ô³o[Ã×d;¡:¶´I?É<ù›þ’sú–òÍC’(ü2ÿ7…2d|¼ù?ËrßÛiÚ>r0áRyò„têAÌÑ«+Á^l¸Zòç ½¶å»yÇÆË?µ7Ÿ¯®Ú‘äv)G{Ý›©'åÒ»>ð2àˆ¦æL-ž??œ
Decoded=123456ds fds àçèé#&çer çer
^rrr 7897ezrzDecoded is equal to Original=true
…here a TEST 3 of encryption/decryption with the modulus and exponent elements of public and private keys://Generation of keys PublicKey publicKey = ....; System.out.println("Public key =" + ((sun.security.rsa.RSAPublicKeyImpl)publicKey)); PrivateKey privateKey = ...; System.out.println("Private key =" + ((sun.security.rsa.RSAPrivateCrtKeyImpl)privateKey)); // Get the modulus and Exponent of public and private keys KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec rsaPubKeySpec = keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class); BigInteger modpublic = rsaPubKeySpec.getModulus(); // = ((RSAPublicKey)publicKey).getModulus()); BigInteger exppublic = rsaPubKeySpec.getPublicExponent(); // = ((RSAPublicKey)publicKey).getPublicExponent()); RSAPrivateKeySpec rsaPrivKeySpec = keyFactory.getKeySpec(privateKey, RSAPrivateKeySpec.class); BigInteger modprivate = rsaPrivKeySpec.getModulus(); // = ((RSAPrivateKey)privateKey).getModulus(); BigInteger expprivate = rsaPrivKeySpec.getPrivateExponent(); // = ((RSAPrivateKey)privateKey).getPrivateExponent(); System.out.println(" **** RSAPublicKey:"); System.out.println(" Modulus public : " + modpublic); System.out.println(" Exponent public : " + exppublic); System.out.println(" **** RSAPrivateKey:"); System.out.println(" Modulus private : " + modprivate); System.out.println(" Exponent private : " + expprivate); // Data String sourceData = "123456ds fds àçèé#&çer çer "+System.getProperty("line.separator")+" ^rrr 7897ezrz"; System.out.println("Original=" + sourceData); // Encrypt data byte[] encryptData = EncryptionRsaEcbPkcs1Padding.encrypt(modpublic, exppublic, sourceData.getBytes()); System.out.println("Encoded=" + new String(encryptData)); // Decrypt data byte[] decryptData = EncryptionRsaEcbPkcs1Padding.decrypt(modprivate, expprivate, encryptData); String finalData = (decryptData!=null)? new String(decryptData):""; System.out.println("Decoded=" + finalData); System.out.println("Decoded is equal to Original=" + (finalData.equals(sourceData)));
…here the outputs:
Public key =Sun RSA public key, 1024 bits
modulus: 119640545002572524162074876403590977724521819906953835044584334393673056623269874048551575214466583338692013946864923643869629755417250776762852900928975400221212653461763170363707824634941857579752131353812321189962302470921868983432333273212462165196125740045294389745266851969500869704002993658134669956039
public exponent: 65537Private key =sun.security.rsa.RSAPrivateCrtKeyImpl@fff5a677
**** RSAPublicKey:
Modulus public : 119640545002572524162074876403590977724521819906953835044584334393673056623269874048551575214466583338692013946864923643869629755417250776762852900928975400221212653461763170363707824634941857579752131353812321189962302470921868983432333273212462165196125740045294389745266851969500869704002993658134669956039
Exponent public : 65537
**** RSAPrivateKey:
Modulus private : 119640545002572524162074876403590977724521819906953835044584334393673056623269874048551575214466583338692013946864923643869629755417250776762852900928975400221212653461763170363707824634941857579752131353812321189962302470921868983432333273212462165196125740045294389745266851969500869704002993658134669956039
Exponent private : 108868021755243832505752434948266651625487636784886383366935187236234286048878072062490222919723654790213725738670317323432705801212493207242160849593365208277168149271759733306735434932388171411986171035282651184823939882411859771870386758804259331674797713118041333080648290829593352145662020438209090922113
Original=123456ds fds àçèé#&çer çer
^rrr 7897ezrzEncoded=~2i
¤ÕìÁù$62?Î4ÝGO?Ô€ƒ&¥?šWµŠ]¿
wÞãøŽï¡S
....Decoded=123456ds fds àçèé#&çer çer
^rrr 7897ezrzDecoded is equal to Original=true
- Error and limitation of RSA
If the following error occurs during the execution of your code:ERROR : javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:346) at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:391) at javax.crypto.Cipher.doFinal(Cipher.java:2087)
….EXPLANATIONS:
The RSA algorithm can only encrypt data that has a maximum byte length of the RSA key length in bits divided with eight minus eleven padding bytes, i.e. number of maximum bytes = key length in bits / 8 – 11. In previous examples, our RSA keys were generated on 1024 bites = 128 bytes, so, the maximum byte length of data to encrypt is : 1024 / 8 – 11 = 128 – 11 = 117 bytes.
…SOLUTIONS:
So, 2 solutions are possibles:
+ use a larger RSA key
+ OR encrypt the data with a symmetric key, and encrypt that key with RSA (recommended approach). That will require to:- Generate a symmetric key
- Encrypt the data with the symmetric key
- Encrypt the symmetric key with RSA
- Send the encrypted key and the data
- Decrypt the encrypted symmetric key with RSA
- Decrypt the data with the symmetric key
Sources : rsa.zip
That’s all!!!
Huseyin OZVEREN