I need crypto-algorithm AES in key wrap mode. Is there some open-source library or implementation that could be helpful?
It is important, that it must be key wrap mode.
The standard SunJCE provider offers an implementation of RFC 3394. Just use the algorithm AESWrap:
Cipher c = Cipher.getInstance("AESWrap", "SunJCE");
c.init(Cipher.WRAP_MODE, secretKey);
byte[] result = c.wrap(someKey);
BouncyCastle supports key wrapping in AES with the AESWrapEngine.
You can look at this StackOverflow post to see more examples of BouncyCastle. The only difference is you will specify the AESWrapEngine instead of the AESEngine.
yes there is a library available named Bouncy Castle you can use that library for wrapping your data encryption key using AES algorithm in WRAP_MODE ,here below code snippet might help you.
public static byte[] wrapKey(SecretKey key, SecretKey keyToWrap) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AESKW", "BCFIPS");
cipher.init(Cipher.WRAP_MODE, key);
return cipher.wrap(keyToWrap);
}
public static SecretKey unwrapKey(SecretKey key, byte[] wrappedKey) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AESKW", "BCFIPS");
cipher.init(Cipher.UNWRAP_MODE, key);
return (SecretKey) cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
}
Related
What's wrong with this?
for (Object obj : java.security.Security.getAlgorithms("Cipher")) {
System.out.println(obj);
}
javax.crypto.SecretKeyFactory.getInstance("AES");
This is the output (JDK 1.6 on Mac OS 10.6):
BLOWFISH
ARCFOUR
PBEWITHMD5ANDDES
RC2
RSA
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
DESEDE
AESWRAP
AES
DES
DESEDEWRAP
PBEWITHSHA1ANDRC2_40
java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(DashoA13*..)
at javax.crypto.SecretKeyFactory.getInstance(DashoA13*..)
...
This is a verified java bug. See https://bugs.openjdk.java.net/browse/JDK-7022467
EDIT: Different java versions support different algorithms, you can also extend it with custom providers and so on. Oracle has a list for java 6 here http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html . For KeyFactory this is DSA.
You don't really need to use SecretKeyFactory. You can create an AES key with the following;
byte[] keyData = ........
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
If you want to do password based encryption (PBE) then simply choose a secure hashing algorithm that gives you a hash the same size as the required key. For example, if you want a 256 bit key for AES, here is a method to build the key;
private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(password.getBytes("UTF-8"));
byte[] key = digester.digest();
SecretKeySpec spec = new SecretKeySpec(key, "AES");
return spec;
}
Edit:
I would recommend against using MD5 and DES unless this is a play project, both have weaknesses and are considered obsolete.
Not all versions of Java provide a SecretKeyFactory for "AES" in their default providers.
If you want to generate a new key, choose the desired number of bits (128, 192, or 256) from a SecureRandom instance, and use that random number to initialize a SecretKeySpec instance.
If you are using password-based encryption, create a SecretKeyFactory for the "PBKDF2WithHmacSHA1" algorithm, and use it to initialize a SecretKeySpec instance as illustrated here.
If you try to print all your providers, you probably missed the one that you need.
Try to call this method and see what it prints out.
for (Object obj : java.security.Security.getProviders()) {
System.out.println(obj);
}
In case for example you need a specific provider (like the Bouncy Castle one), add the dependency to your App and add it on Security Providers as follows:
java.security.Security.addProvider(new BouncyCastleProvider());
and then see again your provider list.
Give a try with all of your algorithm and see which one are supported. An example can be done with jasypt encryption
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.registry.AlgorithmRegistry;
with the following code:
Set<String> supported = new TreeSet<>();
Set<String> unsupported = new TreeSet<>();
for (Object oAlgorithm : AlgorithmRegistry.getAllPBEAlgorithms()) {
String algorithm = (String) oAlgorithm;
try {
SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig();
pbeConfig.setAlgorithm(algorithm);
pbeConfig.setPassword("changeme");
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setConfig(pbeConfig);
String encrypted = encryptor.encrypt("foo");
String decrypted = encryptor.decrypt(encrypted);
supported.add(algorithm);
} catch (EncryptionOperationNotPossibleException e) {
unsupported.add(algorithm);
}
}
System.out.println("Supported");
supported.forEach((String alg) -> System.out.println(" " + alg));
System.out.println("Unsupported");
unsupported.forEach((String alg) -> System.out.println(" " + alg));
I have encrypted the session id at server side using AES but not able to decrypt the encrypted session id at client side, As there isn't any AES library defined for GWT to support AES decryption in java.
The code snippet for AES encryption at server side is :
public static String encrypt(String sessionId)
{
try
{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String key = "Abcdefghijklmnop";
final SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedSessionId = Base64.encodeBase64String(cipher.doFinal(sessionId.getBytes()));
return encryptedSessionId;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
For decryption I am trying with the code provided in this link :
http://reassess.blogspot.in/2009/07/gwt-and-aes-decryption.html
But this isnt working. Please provide any solution if anyone has.
I have tried encryption and decryption in DES but I need to use AES.
AES is not be supported on client side for GWT, but you can use TripleDES. TripleDES is also very much secure implementation.
Here it's another similar question
Here are list of known issues for GWT-crypto.
https://code.google.com/archive/p/gwt-crypto/issues
See #1 issue- AES Encrypted content cant' be decrypted by Java AES Decryptor & Vice Versa
Thank you for taking you time to assist me with this!
THIS POST HAS BEEN EDITED FOR LESS INFORMATION SEE THE EDITED PART
Well I have spend ours of research on this matter and I ended up with a working piece of code..
But Encryption is not a place to make mistakes, and I wanted to ask if my code is actualy secure! It's really important for me because I want to implement it to a program so my code is...
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
public class EncryptFile{
private static final String FILE_IN = "./EncryptFile.java";
private static final String FILE_ENCR = "./EncryptFile_encr.java";
private static final String FILE_DECR = "./EncryptFile_decr.java";
public static void main(String []args){
try
{
Encryption("passwordisnottheactual", Files.readAllBytes(Paths.get(FILE_IN)));
Decryption("passwordisnottheactual");
}catch(Exception e){
System.out.println(e.getMessage());
}
}
private static void Encryption(String Key, byte[] byteArray) throws Exception
{
// Decode the base64 encoded Key
byte[] decodedKey = Base64.getDecoder().decode(Key);
// Rebuild the key using SecretKeySpec
SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
// Cipher gets AES Algorithm instance
Cipher AesCipher = Cipher.getInstance("AES");
//Initialize AesCipher with Encryption Mode, Our Key and A ?SecureRandom?
AesCipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom());
byte[] byteCipherText = AesCipher.doFinal(byteArray);
//Write Bytes To File
Files.write(Paths.get(FILE_ENCR), byteCipherText);
}
private static void Decryption(String Key) throws Exception
{
//Ddecode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(Key);
//Rebuild key using SecretKeySpec
SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
//Read All The Bytes From The File
byte[] cipherText = Files.readAllBytes(Paths.get(FILE_ENCR));
//Cipher gets AES Algorithm Instance
Cipher AesCipher = Cipher.getInstance("AES");
//Initialize it in Decrypt mode, with our Key, and a ?SecureRandom?
AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
byte[] bytePlainText = AesCipher.doFinal(cipherText);
Files.write(Paths.get(FILE_DECR), bytePlainText);
}
}
EDIT
Possible duplicate of Simple Java AES encrypt/decrypt example – JFPicard
Well it could be but these answers Use IVParameterSpec and I wanted to know if
this line of code is actually secure or if it is bad practice:
AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
because I use a new SecureRandom() every time,
and I haven't seen anyone use a SecureRandom object like this.
Encryption key
The password is passes as a string but the Encryption function Base64 decoded it, that is a coding error.
When a password is used the encryption key should be derived from it with the PBKDF2 (aka Rfc2898DeriveBytes) function.
When using key derivation the salt and iteration count needs to be available for decryption, often they are provided in a prefix to the encrypted data.
Encryption mode
No encryption mode is supplied.
Use CBC mode with a random IV.
Just prefix the encrypted data with the IV for use on decryption.
Padding
AES is a block cipher and as such requires the input data size to be a multiple of the block size.
Specify PKCS#7 (née PKCS#5) padding, it will add padding on encryption and remove it on decryption.
On decryption do not return "padding" errors, they can provide a "Padding Oracle" attack.
Explicit
Specify all encryption parameters and sizes.
Do not rely on implementation defaults.
Encryption authentication
Consider if there is a need to know if the data is decrypted correctly.
Versioning
Add a version indicator so that if changes are necessary later there is an compatibility path.
Or consider using RNCryptor which handles all this and more.
Update: (thx Andy for the comment)
If GCM mode is available and interoperability across platforms and libraries is not an issue GCM is arguably a better encryption mode. GCM has authentication and padding build-in making it more robust and an easier secure solution.
Encryption and Decryption successful when encrypt with public key and decrypt with private key :
C# encryption with public key(Successful)
public string EncryptData(string data) {
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml); //public key
var cipher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false);
return Convert.ToBase64String(cipher );
}
Java decryption with private key(Successful)
public static void decrypt() throws Exception{
byte[] modulusBytes = Base64.getDecoder().decode(mod);
byte[] dByte = Base64.getDecoder().decode(d);
BigInteger modulus = new BigInteger(1, (modulusBytes));
BigInteger exponent = new BigInteger(1, (dByte));
RSAPrivateKeySpec rsaPrivKey = new RSAPrivateKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privKey = fact.generatePrivate(rsaPrivKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] cipherData = Base64.getDecoder().decode(cipherByte);
byte[] plainBytes = cipher.doFinal(cipherData);
System.out.println(new String(plainBytes));
}
Problem is Here
When c# encrypt with private key and java decrypt with public key bad padding error occur:
C# encryption with private key(Fail)
public stringEncryptData(string data) {
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xml); //private key
var cypher = rsa.Encrypt(Encoding.UTF8.GetBytes(data), false);
return Convert.ToBase64String(cypher);
}
java decryption with public key (Fail)
public static void decryptPublic() throws Exception{
byte[] modulusBytes = Base64.getDecoder().decode(mod);
byte[] expBytes = Base64.getDecoder().decode(exp);
BigInteger modulus = new BigInteger(1, (modulusBytes));
BigInteger exponent = new BigInteger(1, (expBytes));
RSAPublicKeySpec pubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey publicKey = fact.generatePublic(pubKey);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, publicKey );
byte[] cipherData = Base64.getDecoder().decode(cipherByte);
byte[] plainBytes = cipher.doFinal(cipherData);
System.out.println(new String(plainBytes));
}
I understand public key should use to do encryption and private key for decryption.But in my situation, i need to sent out public key to mutiple clients for decryption on a text encrypted by its private key. Text should be non readable by others except client.
Can anyone see what problem on my code, or suggest a better solution to my problem.
RSA encryption is only secure if a (secure) padding scheme is being used. RSA encryption schemes have been specified in PKCS#1 standards by RSA laboratories (now part of EMC2). These have been copied into RFC, such as RFC 3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1.
For the purposes of this document, an encryption scheme consists of
an encryption operation and a decryption operation, where the
encryption operation produces a ciphertext from a message with a
recipient's RSA public key, and the decryption operation recovers the
message from the ciphertext with the recipient's corresponding RSA
private key.
So encryption with a private key is an undefined operation.
So what to do now:
securely distribute private keys instead of public keys
generate key pairs and securely transport the public key to the sender
if you require authentication/integrity instead of confidentiality, use signature generation instead of encryption
And, whatever you do, read into Public Key Infrastructure (PKI). It's a far stretching subject that you need to understand before you can apply it.
Encrypting with the private key/decrypting with the public key is a legitimate operation in RSA, however it is not used to protect data, it is instead used to authenticate the source of the data and its integrity. In this context the encryption operation is more usually called "signing".
Encrypting using the private key to protect data as you describe is insecure and so the fact that it is not easily done is likely intentional and intended to prevent incorrect use of the algorithm.
Distributing your private key to clients as suggested in the comments is also unwise since you have no control over who they may pass the key onto (accidentally or otherwise).
If you wish to encrypt data so that it can be decrypted by multiple distinct parties, then you should have each of them provide you with their own public key, and use that to encrypt the data separately for each client.
Can we encrypt large files with ECC or it is like RSA works for small only? can anyone please recommend a good website for ECC Java implementation.
Thanks
In general you are required to perform hybrid encryption with ECC. ECIES for instance is basically a key agreement followed by symmetric encryption. So you cannot directly encrypt anything with ECIES, which is the most common ECC method for encryption. Basically you should couple it to a symmetric cipher. This is actually the best scheme for RSA encryption as well, most of the time.
As you can see you can use this directly as a Cipher using CBC mode & PKCS#7 padding, but beware of the large header (117 bytes for a 384 curve, no less). This is required to perform the key derivation. Make sure that the public key is properly validated (I'm not sure about the Bouncy Castle code in this regards, haven't taken a look at it).
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator ecKeyGen = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
ecKeyGen.initialize(new ECGenParameterSpec("brainpoolP384r1"));
// doesn't work, which means we are dancing on the leading edge :)
// KeyPairGenerator ecKeyGen = KeyPairGenerator.getInstance("EC");
// ecKeyGen.initialize(new ECGenParameterSpec("secp384r1"));
KeyPair ecKeyPair = ecKeyGen.generateKeyPair();
System.out.println("What is slow?");
Cipher iesCipher = Cipher.getInstance("ECIESwithAES");
iesCipher.init(Cipher.ENCRYPT_MODE, ecKeyPair.getPublic());
byte[] ciphertext = iesCipher.doFinal(com.google.common.base.Strings.repeat("owlstead", 1000).getBytes());
iesCipher.init(Cipher.DECRYPT_MODE, ecKeyPair.getPrivate());
byte[] plaintext = iesCipher.doFinal(ciphertext);
System.out.println(Hex.toHexString(ciphertext));
System.out.println(new String(plaintext));
}
public static void main(String[] args) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
KeyPairGenerator ecKeyGen = KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME);
ecKeyGen.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair ecKeyPair = ecKeyGen.generateKeyPair();
System.out.println("What is slow?");
Cipher iesCipher = Cipher.getInstance("ECIESwithAES-CBC");
Cipher iesDecipher = Cipher.getInstance("ECIESwithAES-CBC");
iesCipher.init(Cipher.ENCRYPT_MODE, ecKeyPair.getPublic());
String message = "Hello World";
byte[] ciphertext = iesCipher.doFinal(message.getBytes());
System.out.println(Hex.toHexString(ciphertext));
iesDecipher.init(Cipher.DECRYPT_MODE, ecKeyPair.getPrivate(), iesCipher.getParameters());
byte[] plaintext = iesDecipher.doFinal(ciphertext);
System.out.println(new String(plaintext));
}