I have a public/private key set created with sjcl.js in node.js using the P-384 curve. It is constructed like this:
var keyPair = sjcl.ecc.elGamal.generateKeys(sjcl.ecc.curves.c384);
var pubGet = keyPair.pub.get();
var secGet = keyPair.sec.get();
var pub = sjcl.codec.base64.fromBits(pubGet.x.concat(pubGet.y));
var pubKey = "JjcqsHEy9dv8uHQzAoH7do6veTwtK3sxlwB1f/F4PvRXqi36/DCioEaEQu265xtBZ5MQ+SSVlBAaGfLi0NJHe41klrPivyyjATBmE2ZE7tb+Zb0SJhIvL4By89VCVfH/"
var sec = sjcl.codec.base64.fromBits(secGet);
var secKey = "8DDr+bZTVHyC5yLNEpVfSCekNJUTq3S8oibzdS5mp/55bDHgW7Dtkl3D4+naV8Ul"
In Javascript, this can be used to encrypt the string "hello world" like this:
var teststring = "hello world"
sjcl.encrypt(teststring, pub)
which results in the encryption objects with the relevant parameters:
"{\"iv\":\"TEcjccaUsKWzg+UwRxIAtg==\",\"v\":1,\"iter\":10000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"jNHR3i4TJ44=\",\"ct\":\"9p5DCV6AdPFsUYuXqLvELg/pJd1ShesQLOgRkrzQmZUdo7Idfu8I9B74wl5A7CfVG08vbG6Etr6VetrPdQpO/GKWOvN9eisaHeKrOHgBAGLx0GP+Mh3OVX/JtDvr0/F5DK1FRyFLkZ6IPxRn9I+s7UjXQ3HPazPNEVdHuA2Jgi/49jPkFZ0dSQ==\"}"
Again, in Javascript, the keys can be deseralized like this: and in javascript, the key can be deserialised like this
var privateKeyObject = new sjcl.ecc.elGamal.secretKey(
sjcl.ecc.curves.c384,
sjcl.ecc.curves.c384.field.fromBits(sjcl.codec.base64.toBits(privateKey))
);
and used like this to decrypt
var cleartext = sjcl.decrypt(privateKeyObject, message);
Up until here, all works great. However, I now need to be able to perform the same operation in Android using Kotlin.
var pubKey = "JjcqsHEy9dv8uHQzAoH7do6veTwtK3sxlwB1f/F4PvRXqi36/DCioEaEQu265xtBZ5MQ+SSVlBAaGfLi0NJHe41klrPivyyjATBmE2ZE7tb+Zb0SJhIvL4By89VCVfH/"
var secKey = "8DDr+bZTVHyC5yLNEpVfSCekNJUTq3S8oibzdS5mp/55bDHgW7Dtkl3D4+naV8Ul"
var teststring = "hello world"
// deserialize base64 private key into object
val input = secKey
val encoded = Base64.getDecoder().decode(input);
val aesPrivKey = SecretKeySpec(encoded, "P-384");
// this is the same object as created above in the browser with Javascript
val encodedJSONNew = "{\n" +
" \"iv\":\"TEcjccaUsKWzg+UwRxIAtg==\",\n" +
" \"v\":1,\n" +
" \"iter\":10000,\n" +
" \"ks\":128,\n" +
" \"ts\":64,\n" +
" \"mode\":\"ccm\",\n" +
" \"adata\":\"\",\n" +
" \"cipher\":\"aes\",\n" +
" \"salt\":\"jNHR3i4TJ44=\",\n" +
" \"ct\":\"9p5DCV6AdPFsUYuXqLvELg/pJd1ShesQLOgRkrzQmZUdo7Idfu8I9B74wl5A7CfVG08vbG6Etr6VetrPdQpO/GKWOvN9eisaHeKrOHgBAGLx0GP+Mh3OVX/JtDvr0/F5DK1FRyFLkZ6IPxRn9I+s7UjXQ3HPazPNEVdHuA2Jgi/49jPkFZ0dSQ==\"\n" +
"}"
//sjcl.encrypt(teststring, pub)
// Decode the encoded JSON and create a JSON Object from it
val jsonn = JSONObject((encodedJSONNew))
// We need the salt, the IV and the cipher text;
// all of them need to be Base64 decoded
val saltNew = d.decode(jsonn.getString("salt"))
var ivNew = d.decode(jsonn.getString("iv"))
val cipherTextNew = d.decode(jsonn.getString("ct"))
// Also, we need the keySize and the iteration count
val keySizeNew = jsonn.getInt("ks")
val iterationsNew = jsonn.getInt("iter")
// Now, SJCL doesn't use the whole IV in CCM mode;
lolNew = 2
// Cut the IV to the appropriate length, which is 15 - L
ivNew = Arrays.copyOf(ivNew, 15-lolNew)
println("iv: " + Base64.getEncoder().encodeToString(ivNew))
// Crypto stuff.
// First, we need the secret AES key,
// which is generated from password and salt
val factoryNew = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
val specNew = PBEKeySpec(secKey.toCharArray(), saltNew, iterationsNew, keySizeNew)
val tmpNew = factoryNew.generateSecret(specNew)
val secretNew = SecretKeySpec(tmpNew.getEncoded(), "AES")
// Now it's time to decrypt.
val cipherNew = Cipher.getInstance("AES/CCM/NoPadding",
BouncyCastleProvider()
)
// change here to use serialized priv key and iv
cipherNew.init(Cipher.DECRYPT_MODE, aesPrivKey, IvParameterSpec(ivNew));
val finalStringNew = String(cipherNew.doFinal(cipherTextNew));
println("decryption successful: " + finalStringNew)
There is the following error:
Caused by: java.lang.IllegalArgumentException: Key length not 128/192/256 bits.
How can I deserialise this key correctly in Android and make this work?