I want to take a SHA256 hash and generate a key from it using Bouncy Castle (Spongy Castle actually). In the code excerpt that follows, retval is the value returned by the SHA256Digest (a byte array) and finalKey should be the key that was generated from the SHA256 hash.
KeyFactory kf = KeyFactory.getInstance("ECDH", "SC");
X509EncodedKeySpec ks = new X509EncodedKeySpec(retval);
ECPublicKey finalKey = (ECPublicKey)kf.generatePublic(ks);
I get the message "encoded key spec not recognised" when I try to run the code, so I imagine that there is some specific format that retval should be in and that I can't just pass the byte array directly as outputted by the SHA256Digest like I am doing. The Bouncy Castle documentation doesn't seem helpful, or I am just not seeing the relevant section.
In my case I wanted to use SecretKeySpec. The following is an example.
SecretKeySpec finalKey = new SecretKeySpec(retval, "RAW");
Related
I am new to cryptography and am learning how to use Bouncy Castle in Java for crypto purposes.
I know that Python has Crypto-Charm which I have used
import charm.toolbox.ecgroup
serializedKey = charm.toolbox.ecgroup(prime192v1).deserialize(keyInBytes)
How can I do the same for Java?
Try this:
Deserialize:
KeyFactory keyFactory = KeyFactory.getInstance("EC");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
Serialize:
byte[] keyBytes = privateKey.getEncoded();
Maybe you can need this call (depending on your JDK) previous to KeyFactory.getInstance:
Security.addProvider(new BouncyCastleProvider());
This reference could be useful https://www.bouncycastle.org/fips-java/BCFipsIn100.pdf to understand different examples of code enconding.
In chapter
Password Based Encryption and Key Storage
on this section
Encoding Public and Private Keys
there are some examples to get ideas.
I want to generate Random key using AES/ECB/PKCS7PADDING but java does not support PKCS7 padding and in my algo I have to use the same padding, bouncy castle does support PKCS7PADDING but I am unable to understand how to generate key using that
My code :
Security.addProvider(new BouncyCastleProvider());
private byte[] generateSessionKey() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyGenerator kgen = KeyGenerator.getInstance("AES/ECB/PKCS7PADDING", "BC");
kgen.init(SYMMETRIC_KEY_SIZE);
SecretKey key = kgen.generateKey();
return key.getEncoded();
}
I am receiving error of no such algorithm
Key generation for AES does not have to do anything with padding. Padding is required for some modes of operation such as ECB and CBC. But the key itself doesn't rely on the mode or the padding. So you should just use:
KeyGenerator kgen = KeyGenerator.getInstance("AES", "BC");
which will undoubtedly work.
Do not use PKCS#7 padding, substitute "PKCS5Padding" for "PKCS7Padding".
Please take a look here to understand the difference between the padding mechanisms and here for the difference in Java.
I guess Android is using a stripped down Bouncy Castle provider (it was one of the reasons that SpongyCastle was lounged), which would explain the differences between Android and the Java SE provider.
Is it possible decrypt an encrypted RSA (or others, shouldn't matter) private keys using JCE and/or BouncyCastle provider (not using openssl bundle)?
I can read unencrypted keys just fine using PrivateKeyFactory.
Googling this gets me through examples of using PEMReader (from BC openssl bundle) that has a password applied to it, but - don't want to use openssl bundle, don't necessarily want to use PEM format, and I can decode PEM using PemReader (from provider bundle). It's what can I do with it afterwards is the question.
I'm looking for some mega-function, or a series thereof that can do it, i.e. I am not looking into parsing the ASN1 of the encrypted key, figuring out the encryption method, passing the input through the cipher, etc.
If you have an encrypted PKCS#8 key in binary format (i.e. not in PEM format) the following code shows how to retrieve the private key:
public PrivateKey decryptKey(byte[] pkcs8Data, char[] password) throws Exception {
PBEKeySpec pbeSpec = new PBEKeySpec(password);
EncryptedPrivateKeyInfo pkinfo = new EncryptedPrivateKeyInfo(pkcs8Data);
SecretKeyFactory skf = SecretKeyFactory.getInstance(pkinfo.getAlgName());
Key secret = skf.generateSecret(pbeSpec);
PKCS8EncodedKeySpec keySpec = pkinfo.getKeySpec(secret);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(keySpec);
}
If you have a PEM format, remove the header (first line), the footer(last line) et convert the remaining content from base64 to regular byte array.
I am migrating my module from bouncy castle to iaik pkcs7. I need to use blowfish,twofish and idea encryption algorithms in conjunction with iaik.pkcs.pkcs7.EnvelopedDataStream of IAIK library. Idea encryption algorithm Id is present in AlgorithmID class of IAIK but cant be implemented directly(probably because of variable key length). Blowfish is present as separate cipher class but I could not figure out a way to use it along with enveloped data(which is important because I will be using public key encryption method). I can actually encrypt using blowfish,then wrap using enveloped data and some algorithm such as aes and send this but the receiver won't have the algorithm info in that case. Secret key can be passed along with recepientInfo.
If anyone can possible show me the way een basic I may be able to proceed.
Thanks in advance
Atraya
Hi I came up with the solution
ByteArrayInputStream is = new ByteArrayInputStream(message);
AlgorithmID blowfish=new AlgorithmID("1.3.6.1.4.1.3029.1.2","BLOWFISH_CBC","Blowfish/CBC/PKCS5Padding");
byte[] iv = new byte[8];
random.nextBytes(iv);
try{
KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish", "IAIK");
secretKey = keyGen.generateKey();
AlgorithmParameterSpec params = new IvParameterSpec(iv);
keyGen.init(128);
secretKey = keyGen.generateKey();
iaik.pkcs.pkcs7.EncryptedContentInfoStream eci = new iaik.pkcs.pkcs7.EncryptedContentInfoStream(ObjectID.pkcs7_data, is);
eci.setupCipher(blowfish, secretKey, params);
return eci;
}catch(Exception e){
}
Tell me if this way is wrong or can be improved or there is another way of doing this.
thanks
I need to generate an AES key in Java (Android) from salt and password given from .Net WebService. I need to have the same key as the key generated in .net with the same password and salt (using Rfc2898DeriveBytes and AesManaged()).
Here is my code in Android:
char[] passwordAsCharArray = password.toCharArray();
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwordAsCharArray, salt, 1000, 256);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecretKeySpec secretKey = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
Here is code in .net:
byte[] keyBytes = Encoding.Unicode.GetBytes(key);
Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(key, keyBytes);
AesManaged rijndaelCSP = new AesManaged();
rijndaelCSP.BlockSize = 128;
rijndaelCSP.KeySize = 256;
rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
ICryptoTransform decryptor = rijndaelCSP.CreateDecryptor();
When I compare both keys they are different. Any ideas how to generate on Android the same key as in .Net? (I know that the key which have been generated in .net is correct).
Number of iterations in .Net is 1000, salt and password are also the same as in Android.
Ok, it turned out that I dont need exactly the same key (as a byte array). I needed this to decrypt a file (in Java) which have been encrypted in .Net - with this key it gaves me Bad Padding Exception so I think the key was different and that causes the problem, but all I needed to do was to generate IV like a key - that solved my problem. Thanks for response!
It looks like you used the "key" (which should be a password) as a salt in your .NET code, whereas the Java part uses a specified salt. Furthermore, you specified the Unicode character set for decoding your salt, which is weird, the salt should be a random octet string (== byte array) from the beginning.
I would recommend you transform your password and random salt to byte arrays first, compare both using a hexadecimal representation (on your console, or in your debugger) and only then use those as input parameters for the PBKDF2 function in each. I would recommend an UTF-8 encoding for your password.
Always specify all parameters in cryptography, try not to use default, e.g. for the iteration count. If your input is off by a single bit, the output will be completely incorrect, and there is no way to tell which parameter was responsible.
It looks like the Java and .NET PBKDF2 "primitive" is identical on both platforms, there is working code out on the internet.