Java equivalent of Crypto Charm ECGroup serialize / deserialize - java

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.

Related

AES GCM key derivation swift

I'm trying to implement in swift the equivalent of my code in java. Basically is an AES implementation with GCM padding and I'm using a key derivation for that. In swift I'm using the CryptoSwift library.
My issue is that I cannot get the same encrypted text in swift.
After a very long research I couldn't find any solutions for my problem, I even saw the test code of the CryptoSwift library repository to get any ideas but with no luck
This is my java code:
GCMParameterSpec ivParameterSpec = new GCMParameterSpec(128, "ivVector".getBytes());
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), "salt".getBytes(), 1000, 256);
SecretKey tmp = secretKeyFactory.generateSecret(keySpec);
key = new SecretKeySpec(tmp.getEncoded(), "AES");
encryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] encryptedWord = Base64.encode(encryptCipher.doFinal("example".getBytes("UTF-8")));
And this is my swift code:
do{
keyDerivation = try PKCS5.PBKDF2(password: "myPassword".bytes, salt: "salt".bytes, iterations: 1000, keyLength: 32, variant: .sha1).calculate()
let gcm = GCM(iv: keyDerivation, mode: .combined)
let aes = try AES(key: keyDerivation, blockMode: gcm, padding: .noPadding)
let encryptedText = try aes.encrypt("example".bytes)
}catch{
print(error)
}
Any help would be appreciated.
Your IV doesn't match in both cases. In Java you use a string, and in Swift you use the derived key in keyDerivation.
Furthermore, you should make sure that you use the same character encoding. I'd not use getBytes or similar for either language. Explicitly specifying UTF-8 is probably best.
Note that the Java PBKDF2WithHmacSHA1 may handle password encoding in a rather peculiar way, so some kind of input validation on the password is probably in order.
Needless to say, the salt should be random for each call to encrypt, not static. I presume this is just test code though.

PEM to PrivateKey

I need to convert an RSA private key located in memory in PEM format into a PrivateKey on Android.
The problem seems to have been solved for public keys but I'm struggling to get it to work for a private key. I'm trying the following code:
String pemkey = "MIICWwIBAAKBgQDIuL0SzG1+wgyaoyDyHvYIaG10ePXBHqaKTnYyZfY5RzaEFLE/vBdFN2Di7AMH3/5iN/YFQqLsVjKqzX3E3LM2dJOZ9qSWeYArSyQPbhy0eM/3amwchvtLvhVLm2UqVFLjiPGlyYX3D75ETD5tmgulAc5ZDRtGqYVoLKPmZ0USPwIDAQABAoGAErfDjf65UUJISZ1fw6Rmfic62csz47P3hNtHQ3Dlsra020FQvChOpTpCUzb+G1xkjQU58Iijx9VL+Uiba2HHZmiJX2LgS3KKqKFZKmbKZnZQTiw+2o+4AXhtcAYfSAJE9TgRPEhwhZmzV2cvfUk5AjnOghSn2gGjdD1g4xtH22ECQQD/ZbfEd2HEGqHf6j/AVMW+N/Q1xtYIB8r0CWxF6cNw5iq/8Ce9ujpnAFi0vgtojyKDlgwBp4XMU2C4is49EkFhAkEAyTH96mS8dExAAmi3Mm2seUIEOtKwuLD6BEECecPyZSIOd24tfNbmA7Ri6MpGjyLZoNoJQ0AJGcnWU1tnc8bXnwJAS+jYyP1OwrHDwUDnt+u6ZoJNBJrXzMU8LnKKivEjFPBkbm4b8cljSHAS7Y266FX6xS+Y2/kFzKhPjCo9iGtfoQJAOv39hYyj9TWmTw6FKLQfri49L0I3ru+1Xynwn+NkX2Ls+vfDPqeEKfHqTneA2NdPGGrV7HIKORWFUkuqubfD4QJAK60RuhDSeH+ZljcYLhbHLoTnja/uTcvDAd0M4ll2HUNId4jPbYl1qw7OQwfg8apKmGwp7HGW50o/EItvvJrR7w==";
byte[] encoded = Base64.decode(pemkey, Base64.DEFAULT);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey sessionkey = kf.generatePrivate(keySpec);
(The key is not the same as for my Bitcoin wallet so don't bother ^^)
The last line gives the error
java.security.spec.InvalidKeySpecException:
Must use RSAPublicKeySpec or PKCS8EncodedKeySpec;
was java.security.spec.X509EncodedKeySpec
I tested the pemkey string to be ok in other languages (e.g. Python RSA.importkey) and it works fine.
Edit:
On a suggestion by a comment (and the answer to the question linked as doublicate), I also tried with X509EncodedKeySpec replaced by PKCS8EncodedKeySpec. Then the new error I get is
java.security.spec.InvalidKeySpecException:
java.lang.RuntimeException:
error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
Thanks to comments by Greggz and James I was able to get it to work. There were two problems:
X509EncodedKeySpec had to be replaced by PKCS8EncodedKeySpec
The provided pemkey was PKCS#1 (to be recognized by 'BEGIN RSA PRIVATE KEY') but needs to be PKCS#8 (to be recognized by 'BEGIN PRIVATE KEY').

How to decrypt a private key in Java (without BC openssl)

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.

How to generate a key from a SHA256 hash using Bouncy Castle?

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");

blowfish encryption with iaik pkcs7 EnvelopedData

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

Categories