Implementation of ECC in Java - java

While trying to encrypt a given input using Elliptic Curve Cryptography in Java I'm using the following algorithms for generating the cipher and the key:
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA");
Cipher cipher = Cipher.getInstance("ECIES");
Now as expected, the cipher isn't accepting the keys generated by the ECDSA algorithm. I get the error as - must be passed IE key.
I searched for the ciphers being supported by these 2 methods here: http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html#Cipher
Unfortunately no else algo is supported for ECC. Has anyone used ECC generated keys to encrypt/decrypt an input? Which algo should I use for both so that they don't clash with each other?

According to http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator, you need to pass "EC" for an instance of the KeyPairGenerator for ECC.

Also for a more feature-rich cryptography implementation take a look at Bouncycastle.

Related

How to decrypt data in Java that was encrypted in Obj-c

I am encrypting in ojb-c with SecKeyEncryptedData and trying to decrypt in Java with javax.Cipher and hitting a problem.
I recently moved to doing long blocks and have needed to use a symmetric encryption with the AES key encrypted with the asymmetric key pair. I am having problems decoding.
I have the iOS key kSecKeyAlgorithmRSAEncryptionPKCS1 working for asymmetric data matched with Cipher.getInstance("RSA/ECB/PKCS1Padding") in Java. This decodes the short blocks.
As I need to send longer blocks, and am trying to switch to kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM on iOS and it encrypts fine, but i cannot find the method to use in Cipher to decrypt it and do not understand if it needs to be done in 2 steps in the cloud in Java.
OBJ-C:
SecKeyAlgorithm algorithm = kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM;
NSData* cipherText = nil;
cipherText = (NSData*)CFBridgingRelease( // ARC takes ownership
SecKeyCreateEncryptedData(self.pubKey, algorithm,
(__bridge CFDataRef)data, &error));
Java:
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, priv);
byte[] dog = decoder.decode(encString);
dec = cipher.doFinal(dog);
res = new String(dec);
} // handle errors
The decode obviously fails.
So my question is in 2 parts.
is there a Cipher type that will do the decode needed or do i need to break out the encrypted AES key and decrypt it first?
If i need to break it up, how long is that encrypted AES key part of the data block and, if you know the ciphers for that it would be fantastic.
is there a Cipher type that will do the decode needed
You may read the Cipher documentation. I believe you are looking for RSA/ECB/OAEPWithSHA-256AndMGF1Padding
I see the designation doesn't exacly match with the Obj-C name, but this is a common standard so it may worth a try
As I need to send longer blocks, and am trying to switch to kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM
You may try to search for "hybrid encryption". Asymmetric ciphers are VERY slow comparing to symmetric ciphers and intended to encrypt only limited amount of data.
Some implementation may encrypt longer data anyway (for each 256 bit input providing 2048 o 4096 bit output), Java will simply complain and stop
So proper encryption would be
encrypt data with a radom key (DEK - data encryption key) using a symmetric cipher
encrypt the DEK using an asymmetric public key
If the kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM would be not counterpart (compatible) with RSA/ECB/OAEPWithSHA-256AndMGF1Padding, you may still use the PKCS#1 1.5 padding (the old one) with this approach.
Edit: this asnwer may be useful when working with OAEP too RSA/ECB/OAEPWithSHA-256AndMGF1Padding but with MGF1 using SHA-256?

Trouble when generating a secretKey with Blowfish

So I'm trying to get a secretKey for Blowfish using bouncycastle as this:
SecretKeyFactory factory =SecretKeyFactory.getInstance("Blowfish", "BC");
but it throws the following exception:
Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: Blowfish for provider BC
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at javax.crypto.JceSecurity.getInstance(JceSecurity.java:96)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:204)
at Main.main(Main.java:112)
How do I solve this? (it also happens when I use "RC4" instead of "Blowfish", but it works with "DES" and "AES")
Unlike asymmetric keys which have internal structure, you don't really need a factory for 'raw' secret (symmetric) keys, only those that use a derivation algorithm (PBE*, PBKDF2, etc). The standard (SunJCE) factories for DES and DESEDE do check/fix length and parity FWLIW, but the BC ones (plus AES beginning with 1.56) don't even do that. RC4 and Blowfish (among others) accept variable-length keys with no constraints on the bits, so there's not really anything the factory could do even if it were provided.
Just put your key material in a SecretKeySpec and use that. Unlike the other *KeySpec types, SecretKeySpec 'is-a' SecretKey (to be exact implements that interface) and can be used where a SecretKey or appropriate Key is needed, particularly in Cipher.init(mode, key ...)
If you really want to generate a key, not use/convert an existing one, you don't want a factory anyway. In spite of the name, factories only convert, they don't create. To generate a key you either need a KeyGenerator (or for asymmetric KeyPairGenerator) and those DO exist for RC4 (aka ARC4) and BLOWFISH in BC, and also in standard SunJCE but using the names ARCFOUR and BLOWFISH; or (for raw symmetric) just use SecureRandom to generate the correct number of bytes, and use that.

Java AES encryption similar to aesCryptoServiceProvider

Well I want to generate the AES key using java and mentioned is the specification based on ".NET" utility that need to follow while generating the key in JAVA program
Specification: "Generate AES key using AesCryptoServiceProvider with Mode = ECB, Padding = PKCS7, KeySize = 256 &
BlockSize = 128."
I researched a lot but didn't get similar things that can be used in Java to generate the AES key.
Can anyone please guide me how to move ahead with the same to create the AES key with above specification mentioned?
For an AES key either use random bytes obtained from a CSPRNG or derive the key from a passphrase with PBKFD2.
Do not use ECB mode in new work and update legacy work ASAP, it is not secure, see ECB mode, scroll down to the Penguin. Instead use CBC mode with a random IV, just prefix the encrypted data with the IV for use in decryption, it does not need to be secret.
Notes:
The Java base implementation limits the key size to 128-bits (which is fully secure), in order to use a larger key you need to you have to use Java Cryptography Extension:
Java 6 JRE, Java 7 JRE, Java 8 JRE
(Thanks to Robert for the versions info and links!)
AES only has one block size: 128-bits.
For Java see the Documentation Java Cryptography Architecture Reference Guide and in particular The Cipher Class.

Breaking down RSA/ECB/OAEPWithSHA-256AndMGF1Padding

Java has a mode called RSA/ECB/OAEPWithSHA-256AndMGF1Padding. What does that even mean?
RFC3447, Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1, section 7.1.2 Decryption operation says Hash and MGF are both options for RSAES-OAEP-DECRYPT. MGF is it's own function, defined in Section B.2.1 MGF1 and that has it's own Hash "option" as well.
Maybe the Hash "option" in RSAES-OAEP-DECRYPT and MGF1 are supposed to be the same or maybe they're not, it is unclear to me. If they are then I guess when you have RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING that means sha256 should be used for both. But if they're not supposed to be the same then you could have sha256 used for RSAES-OAEP-DECRYPT and, for example, sha1 used for MGF1. And if that's the case then what function is sha256 supposed to be used for? And what hash algorithm is supposed to be used for the other function?
And what does ECB mean in this context? ECB is a symmetric block cipher mode. Electronic Code Book. Maybe it's supposed to mean how Java deals with plaintext's that are larger than the modulo? Like maybe splits the plaintext into chunks that are as big as the modulo and then encrypts each one with RSA and concatenates them together? I'm just guessing..
The default for OAEP is to use SHA-1 for MGF1 (but see the edit on the end of this answer). Note that the hash chosen doesn't have that much impact on the security of OAEP, so mostly it will be left to this default.
We can easily test this by testing it against "OAEPPadding" and OAEPParameterSpec:
// --- we need a key pair to test encryption/decryption
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024); // speedy generation, but not secure anymore
KeyPair kp = kpg.generateKeyPair();
RSAPublicKey pubkey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privkey = (RSAPrivateKey) kp.getPrivate();
// --- encrypt given algorithm string
Cipher oaepFromAlgo = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
oaepFromAlgo.init(Cipher.ENCRYPT_MODE, pubkey);
byte[] ct = oaepFromAlgo.doFinal("owlstead".getBytes(StandardCharsets.UTF_8));
// --- decrypt given OAEPParameterSpec
Cipher oaepFromInit = Cipher.getInstance("RSA/ECB/OAEPPadding");
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSpecified.DEFAULT);
oaepFromInit.init(Cipher.DECRYPT_MODE, privkey, oaepParams);
byte[] pt = oaepFromInit.doFinal(ct);
System.out.println(new String(pt, StandardCharsets.UTF_8));
The code will fail with a padding related exception if you substitute "SHA-256" for the MGF1 as parameter.
The reason why the extended algorithm is needed at all is compatibility with other Cipher algorithms. Code written for e.g. "RSA/ECB/PKCS1Padding" doesn't use any parameters, let alone OAEP parameters. So without the longer string OAEP cannot function as drop in replacement.
The mode of operation "ECB" doesn't mean anything in this context, it should have been "None" or it should have been left out completely. You can only encrypt a single block using the RSA implementation of the SunRSA provider.
If you want to encrypt more data, create a random (AES) symmetric key and encrypt that using OAEP. Then use the AES key to encrypt your specific data. This is called a hybrid cryptosystem as it uses both asymmetric and symmetric primitives to encrypt data.
Note that OAEP is not supported in JDK 7 (1.7) or earlier. OAEP is included in the implementation requirements for Java runtimes since Java 8:
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
Some protocols may require you to use SHA-256 or SHA-512 within the padding, as SHA-1 is being deprecated for most use - even if it is not directly vulnerable for this kind of purpose.
EDIT: this was written mostly with Java in mind. By now many other libraries seem to take a somewhat different approach and use the same hash for the (mostly empty) label and MGF1 - which does make more sense. If you have an invalid OAEP ciphertext you should first make sure that the right "default" is being used. It is impossible to wrong any library implementation for choosing their own default; in the end it is up to the protocol to define the hashes used. Unfortunately no mandatory default exists - which is especially a problem if protocol owners forget to fully specify a configuration for the algorithms.

EC ElGamal in Bouncy castle for Java

(this is purely for academic purposes)
I have got RSA and ElGamal implemented using bouncy castle, But I am not sure how to impliment EC ElGamal. section 4.4 in the bouncy castle spec says: "The org.bouncycastle.crypto.ec package contains implementations for a variety of EC cryptographic transforms such as EC ElGamal" However it doesn't go about explaining how to use it.
I have got as far as using the named curves in the key pair generation
ECNamedCurveTable.getParameterSpec("prime192v1")
But I don't know the algorithm reference e.g. "AES", "RSA" to put the initialisation calls
KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm, provider);
Or if anything else needs to be changed when using ECC? I take it the message size limit in ECC is based on the curve size? the above example being 192-bits.
With ECElGamalEncryptor you can only encrypt a point on the curve. This is actually the same with textbook RSA (i.e. modular exponentiation) where you can only encrypt a big integer (less than the modulus).
You should be using a scheme such as ECIES to encrypt with Elliptic Curve cryptography. ECIES basically uses static Diffie-Hellman to encrypt messages.

Categories