I have the following keypair created with SJCL.js on node.js
var keyPair = sjcl.ecc.elGamal.generateKeys(sjcl.ecc.curves.c384);
I understand that I need somehow elGamal in Android as well.
I want to implement a chat feature whereby every text chat to be sent will be encrypted with the public key of the receiver.
How can I use these elGamal public keys to perform an encryption (and the private key to decrypt respectively) in Android?
So far, I have just found support for RSA keys.
Related
I am having a slight problem with understanding the concept of RSA signing and verifying.
The problem is that I can create key pair (public and private key) which is perfectly fine.
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
random = SecureRandom.getInstance("SHA1PRNG");
keyGen.initialize(2048, random);
KeyPair pair = keyGen.generateKeyPair();
myPrivateKey = pair.getPrivate();
myPublicKey = pair.getPublic();
Signing and verifying are as follows:
//Singing with private key
Signature s = Signature.getInstance("SHA1withRSA");
s.initSign(javaPrivateKey);
//Verifying with public key
Signature s = Signature.getInstance("SHA1withRSA");
s.initVerify(javaPublicKey);
When I print myPrivateKey and myPublicKey, I see modulus(n) and public exponent(e) are the same for public and private key.
I have converted public and private keys to base64 and hex and I get the different values which is perfectly fine. However, I cannot sign the message with base64 or hex. I can sign it only with what I get from this:
myPrivateKey = pair.getPrivate();
I am aware of that verifying needs to be done with the public key which is visible to everyone. When the message is verified by the receiver, does the receiver use modulus and exponent only? What part of the public key needs to be shared by the sender? Modulus and exponent or Base64 or hex value of the key?
Yes, the receiver uses modulus and exponent only; there are no other components that are required mathematically speaking to verify a signature for RSA.
The mathematical operations are performed using large numbers (BigInteger values commonly when RSA is implemented in software). To perform any kind of calculation the implementation must regenerate these numbers. How these numbers are transmitted doesn't matter to the algorithm.
Commonly RSA public keys are encoded using something based on PKCS#1, which specifies the public key format using ASN.1 (which defines the structure) and BER/DER (which defines the encoding of that structure). Of course, different protocols may use different encodings of public keys. PGP for instance uses an entirely different "package format" to encode keys.
Java however returns a SubjectPublicKeyInfo structure which is defines in the X.509 (certificate and CRL) specifications; besides the modulus and exponent is also contains an algorithm identifier to show that it is an RSA public key. So this structure can also be used to distribute other kind of key values. It can be retrieved by calling getEncoded() on the RSAPublicKey instance - assuming that this instance is compatible with the Oracle provided one - they generally are. Android's implementations certainly should be compatible with this structure. Note that the SubjectPublicKeyInfo structure contains the PKCS#1 public key structure inside of it.
To reverse you need an KeyFactory.getInstance("RSA") and derive the key using X509EncodedKeySpec, initialized with the given byte array.
If you need textual strings instead of binary then you can convert the bytes returned by getEncoded() into base 64 and hexadecimals. Of course, in that case, you need to reverse the encoding (i.e. decode) the result before being able to decode the bytes themselves.
It is also possible to encode the modulus and public exponent yourself. You can retrieve them using RSAPublicKey.getModulus() and RSAPublicKey.getPublicExponent(). To reverse them back into an RSAPublicKey you can use KeyFactory.getInstance("RSA") and RSAPublicKeySpec. That way you can for instance just create a string "(<modulus>, <exp>)" and use that to distribute the key. Generally you would want to keep to predefined standards though.
Not covered in this answer is the fact that to verify with a public key you first need to establish trust in the public key. If you cannot trust the public key then you don't know who created the public key. In that case you can also not trust the result of your verification operation; the signature may have been created with a key pair of an adversary. Delving into Public Key Infrastructures (PKI / PKIX) is a bit too much for this answer though.
Likewise: SHA-1 is not considered secure anymore, especially for signature generation / verification. You would want to use at least SHA256withRSA or - slightly more advanced and somewhat more secure - an RSA scheme that uses PSS. 2048 bits is ever so slightly too small for comfort; using a 4096 bit key is advisable if your scheme allows it.
I'm looking to encrypt a string using DES in one app and then decrypt it in another app. Currently I think its not working because the key to encrypt is generated randomly and so in the second app, the key generated when attempting to decrypt is different.
I need to be able to set my own key for when I am encrypting and then set the same key in the second app when decrypting but cannot find an explicit method on how to do so
Currently my key is being generated as follows:
KeyGenerator keygenerator = KeyGenerator.getInstance("DES");
SecretKey myDesKey = keygenerator.generateKey();
How can I create a dummy key to use (e.g. 12345678)
Thanks
see this article, perhaps it can help you:
http://examples.javacodegeeks.com/core-java/crypto/encrypt-decrypt-with-des-using-pass-phrase/
I'm developing an Py4a (Python in SL4a) application running on an Android phone.
The application collects some sensitive data, and then sends it via e-mail, using the smtplib module.
To assure necessary protection, I need to encrypt that information.
As phone is considered to be unsafe device, I have to use the public-key encryption, and only recipient's public key should be stored in the phone.
The standard Py4a distribution contains two packages supporting public key cryptography:
the ssl and gdata.
Unfortunately none of them provides a ready to use function, allowing me to encrypt longer information with the private key.
Well, I know that in fact I should generate a random temporary symmetric key, encrypt my information with that key, and finally encrypt only this key with the recipient's public key. However there are some details which must be considered to obtain secure solution...
So here my question comes. Is there any simple encryption library, well suited to Py4a (ie. based on the cryptographic libraries already available in Py4a - like ssl and gdata.Crypto) providing easy to use public key encryption?
Update 2013.06.13
I have performed some experiments with the gdata library in Py4a.
Finally I have get the following "quick&dirty" solution:
import gdata.tlslite.utils.keyfactory as rk
#Generate the recipient's RSA key
sec=rk.generateRSAKey(1024)
#obtain the publickey, which will be stored
#in the sender mobile phone
pubxml=sec.writeXMLPublicKey()
print pubxml
#Create the public key from XML
pub=rk.parseXMLKey(pubxml)
#
#Now lets simulate the sender
#It has only access to "pub"
#
import gdata.tlslite.utils.PyCrypto_AES as sk
import gdata.tlslite.utils.cipherfactory as cf
#Generate random key and initioalization vectors
key=sk.getRandomBytes(32)
iv=sk.getRandomBytes(16)
#Here we should check if the key and iv are reasonable
#Now we accept them as they are
#Text to encrypt
txt1="Strictly secret unknown text!"
#Pad the text to the length N*16
padlen=16-(len(txt1) % 16)
if padlen:
txt1=txt1.ljust(len(txt1)+padlen, " ")
#Create the AES key
ak=cf.createAES(key.tostring(),iv.tostring())
#Encrypt text
ctxt1=ak.encrypt(txt1)
#Encrypt key and initialization vector with recipients publickey
ckey1=pub.encrypt(key+iv)
#
# Now we simulate the recipient
# It has its secret key 'sec', and received encrypted key
# and iv from the sender in ckey1. It also receives ctxt1
#
pkey1=sec.decrypt(ckey1)
pkey=pkey1[0:32]
piv=pkey1[32:48]
# Now we decipher the text
pak=cf.createAES(pkey.tostring(),piv.tostring())
ptxt1=pak.decrypt(ctxt1)
# Print the deciphered text
print ptxt1
Probably this solution is far from being optimal, but it at least works.
Because the phone is an unsecure device, you cannot trust anything that is computed on the phone. If you want something done securely, do it on your server.
As for your question, this is just how public cryptography (at least RSA) works: you cannot encrypt any data that is longer than the key. The reason there are not libraries for this is that it is impossible. If you need secure email use S/MIME or GPG and don't try to reinvent the wheel. Also note that since the key needs to be in the app, anyone can extract it and decrypt your data. If you just want to send data securely, a better approach might be so send the data over HTTPS. Then you don't need to manage client keys and your data will be protected in transit.
I am needing to know is there a way with iphone and android to send a file encrypted based on a public/private key system?
-- Edit after below post --
Basically I am wanting to:
1. Take a file off an iphone/android
2. Public key encrypt it
3. Email it
4. Manually private key unencrypt it
Thanks
Implement RSA at both side iPhone and Android. You can use openssl to implement RSA at both side. It is peer reviewed and i have used once. And it is working at both side. Generate key pair and send public key to all and keep private key confidential. For example Encrypt file at iPhone side using public key and decrypt the file at Android side with private key .
no key distribution, public and private keys will be known by users (random key generator will not be used). I have to encrypt hashed message with private key in order to provide signature
message will only 10-20 characters, so system can be as simple as it is possible
For generating a digital signature, you don't need to encrypt the hash. Signing is a separate crypto primitive; the hash is not encrypted raw anyway, there's some padding. That said, the code is:
Signature Signer = Signature.getInstance("SHA1withRSA");
Signer.initSign(MyKey, new SecureRandom()); //Where do you get the key?
byte []Message = MyMessage(); //Initialize somehow
Signer.update(Message, 0, Message.length);
byte [] Signature = Sign.sign();
Okay, back up and tell us what you want. Are you trying to get privacy by protecting the contents of the message, or guarantee authenticity by showing that the message really came from the originator?
If you're looking for privacy, RSA isn't the way to go: use RSA to generate a private/public pair, and then use them to excahnge keys -- or exchange keys out of band. Use a streaming algorithm like AES to encrypt the message.
If you just want signature to show the message was originated by who you think it was, then have a look at the Wiki article on digital signature -- it's reasonably straightforward.