EC ElGamal in Bouncy castle for Java - 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.

Related

How to find out the PKCS of a PublicKey - Cryptography

A simple question but trick for me to know how to do it.
I received a Public Key from the client and I'd like to know which Standard this public key is following.
I.e: PKCS#1, PKCS#2, PKCS#3 and so on.
Why do I need it?
Because I want validate a signature given that I already have the signature and the text encrypted.
Most PKCS don't involve public keys at all. All are listed in wikipedia.
PKCS1 defines ASN.1 formats for publickey and privatekey for RSA (only). These are pretty much the only keys described as conforming to any PKCS.
PKCS2-4 and 6 no longer exist, although OpenSSL has caused the PKCS3 format for DH to persist -- but DH is not used for signature.
PKCS5 doesn't involve publickey.
PKCS7 can use publickeys for encryption and/or signature verification of a message and/or can convey one or more X.509 certificate(s) (each) containing a publickey. Such certificate(s) can be for any algorithm.
PKCS8 doesn't involve publickey.
PKCS9 doesn't directly involve any key, although some attributes can be used in an X.509 certificate for a publickey.
PKCS10 is used to request an X.509 certificate, and represents a publickey in the same way as that certificate, which can be for any algorithm.
PKCS11 is an interface; although many types of keys can be transferred over it, those keys are not 'PKCS11' keys.
PKSC12 in practice contains a publickey only as an X.509 certificate, for any algorithm.
So if a key is described as 'PKCS' it's almost certainly PKCS1 and thus RSA. But many publickey algorithms now exist and are more or less widely used (DSA/DH/MQV/EG some, ECDSA/ECDH/ECIES and EdDSA/X a lot, GOST a little, postquantum little but growing) that are not covered by any PKCS.

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.

Symmetric key generation after ECDHC using KDF with SHA-256

I want to generate a Symmetric key using Single-step Key Derivation Function (KDF) based on SHA-256.
I think key derivations are in the lightweight API of Bouncy Castle since 1.50.
I have successfully generated the secret key "Z".And have a code for generating KDF from Z.
Please kind the code below
byte[] data = new byte[16];
SecretKey secretKeyA = generateSharedSecretZ(keyPairA.getPrivate(),
keyPairB.getPublic());
System.out.println(bytesToHex(secretKeyA.getEncoded()));
//Single-Step KDF specification using SHA256
Digest digest = new SHA256Digest();
System.out.println(digest.getDigestSize());
HKDFBytesGenerator kDF1BytesGenerator = new HKDFBytesGenerator(digest);
kDF1BytesGenerator.init(new HKDFParameters(secretKeyA.getEncoded(),
generateSalt(), null));
kDF1BytesGenerator.generateBytes(data, 0, 16);
System.out.println(new String(data));
System.out.println(data.length);
Using the below method for generating the salt
private static byte[] generateSalt() throws NoSuchAlgorithmException {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[32];
random.nextBytes(salt);
return salt;
}
I am using org.bouncycastle.crypto.generators.HKDFBytesGenerator for generating the Symmetric key using sha-256. Is the above implemention, a single-step KDF? Am I missing any relevant steps in generating the Symmetric key using single-step KDF using sha-256 according to the NIST 800-56A document.
Is there any standard size for the Symmetric key. Iam using the Symmetric key for Generates the MAC as per GCM-GMAC specification.
Beware that you need to communicate the salt value if you use one in HKDF. For a KDF after Key Agreement - which should already provide you with enough entropy in the secret - I would consider it strictly optional.
Yes, it is a single step KDF (at least it doesn't use multiple iterations as would be expected for a Password Based Key Derivation Function.
No, you don't seem to be missing any steps (not that there are that many). You could consider using "GCM.GMAC".getBytes(StandardCharsets.US_ASCII) as value for info; this makes it easier to generate more keys later on.
There is no standard size for symmetric keys. Modern crypto would require at least 128 bits (16 bytes). AES uses 128, 192 or 256 bit keys, neither of which is a bad choice. AES-128 may be slightly faster and does not require the Unlimited Crypto files for Java. AES-256 may protect against some future attacks that uses Quantum Cryptoanalysis.

Is there a difference between ECDH and ECDSA keys?

I'm building a network application that uses BouncyCastle as a cryptography provider. Let's say you have this to generate a keypair:
ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime192v1");
KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC");
g.initialize(ecSpec, new SecureRandom());
KeyPair pair = g.generateKeyPair();
I'm confused as to why you're getting an instance of an ECDSA KeyPairGenerator. Why doesn't it just say EC? I know that there's an ECDH Key type that is shipped with BouncyCastle, but I thought that the two represented the same stuff about the points on the curve -- or am I completely wrong with the theory behind it?
The reason that I ask is that right now my application uses ECDH fine to establish an AES secret key, but now I want to use the same EC key to sign each message using ECDSA.
ECDSA and ECDH are from distinct standards (ANSI X9.62 and X9.63, respectively), and used in distinct contexts. X9.63 explicitly reuses elements from X9.62, including the standard representation of public keys (e.g. in X.509 certificates). Hence, ECDSA and ECDH key pairs are largely interchangeable. Whether a given implementation will permit such exchange, however, is an open question. Historically, (EC)DSA and (EC)DH come from distinct worlds.
Note, though, that usage contexts are quite distinct. There is a bit more to cryptography than computations on elliptic curves; the "key lifecycle" must be taken into account. In plain words, you do not want to manage key agreement keys and signature keys with the same procedures. For instance, if you lose your key agreement key (your dog eats your smartcard -- do not laugh, it really happens), then you can no longer decrypt data which was encrypted relatively to that key (e.g. encrypted emails sent to you, and stored in encrypted format). From a business point of view, the loss of a key can also be the loss of an employee (the employee was fired, and was struck by a bus, or retired, or whatever). Hence, encryption keys (including key agreement keys) must often be escrowed (for instance, a copy of the private key is printed and stored in a safe). On the other hand, loss of a signature key implies no data loss; previously issued signatures can still be verified; recovering from such a loss is as simple as creating a new key pair. However, the existence of an escrow system tends to automatically strip signatures of any legal value that could be attached to them.
Also, on a more general basis, I would strongly advise against using the same private key in two distinct algorithms: interactions between algorithms have not been fully explored (simply studying one algorithm is already hard work). For instance, what happens if someone begins to feed your ECDH-based protocol with curve points extracted from ECDSA signatures which you computed with the same private key ?
So you really should not reuse the same key for ECDH and ECDSA.

Implementation of ECC in 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.

Categories