A: See the demo and test packages.
There are a few simple demonstration programs in the org.logi.crypto.demo package and you may also want to look at the more complicated code in the org.logi.crypto.test package.
On Tue, Feb 08, 2000 at 03:39:51AM +0800, Simon Liu Sai Man wrote:A: You must call EncryptCBC.flush()
I have downloaded your crypto library to perform encryption and decryption. However, I have faced a problem.
I have generated a RSA Key pair, and using CBC mode as Cryptographics mode.
I then pass a message, say "I am Neko", which is 9 bytes, to encrypt, by calling the method "EncryptCBC.encrypt(message,0,message.length)", which returns a byte array, with 128 bytes, say enc.
And the I try using the private key to dectypt that message, by calling the method "DecryptCBC.decrypt(enc,0,enc.length)". However, it does not work, the return byte array with length 0.
So, are there any mistakes in the method calling??
P.S. of course I have initialized both method with a Key Pair of public key and private key to the constructor EncryptCBC and DecryptCBC respectively.
This is all fine, except for one missing detail. Here is what is happening:
- You initialize the EncryptCBC object with an RSA key. It looks at the key and decides that it needs a block-size of 128 bytes. That presumably means that you are using a 1024 bit key-pair.
- You send it a string about a cat? Anyway, you send it some data to encrypt and because this is the first bit of data it gets, it creates an IV (initialization vector) which is one block of random bits. The IV is there to make sure that if you encrypt the same data twice, the ciphertext looks different.
However, the 9 bytes you want to encrypt are not enough to fill an entire block, so they are stored and will be encrypted when the block fills up.
What you get is the IV and *no ciphertext*.
- The DecryptCBC gets your array of 128 bytes of IV and initializes itself with that. It sees no cicphertext following, so it returns an empty array as it should.
After calling the EncryptCBC.encrypt method with the last bit of data, call the flush() method. This causes the internal buffer to be filled with random bits, encrypted and returned. The DecryptCBC object will now return an array containing the plaintext followed by the random data.
Wrap EncryptCBC and DecrytpCBC objects in EncryptStream and DecrytpStream objects respectively. Write the string to the EncryptStream and call flush(). When decrypting, read a string from the DecryptStream and then call drain() to get rid of the random padding.
You probably don't want to use RSA to encrypt actual data, but rather to encrypt session keys, preferably by using the EncryptedKeyEx classes in conjunction with the EncryptStream and DecryptStream classes.
A: Use the Fingerprint.create() method.
Normally, passwords are not encrypted, but hashed. Hashing can be thought of as one-way encryption; there is no key to get back the original password if you know the hashed password.
In logi.crypto this could be done with:String password = getPassword(); Fingerprint fp = Fingerprint.create(password,"SHA1");
In the above, "SHA1" is the name of the hash-function used. It can be replaced with "MD5" and possibly others will be added in the future.
Please see the next question.
A: Use the QRAuth classes or generate RSA keys from the password
In many authentication systems the user types in a password which is sent to the server. The server hashes the password and compares the hash to the value stored in a database. There are serious problems with this protocol!
The password could be captured on the network connecting the client and the server. This can be alleviated by sending the password encrypted, for example through an CipherStreamClient initialized with a DHKeyExClient.
The other problem is that the user has no guarantee that he is talking to the correct server and might be giving his password away to the wrong entity.
A better way is to create a pair of CipherStreamClient and CipherStreamServer objects, and execute the appropriate QRAuthClient and QRAuthServer objects on them. This authenticates the client to the server and the server to the client without ever sending the secret to the other.
The QRAuth objects must be initialized with a secret CipherKey object. This could be created by hashing a password and passing the bytes of the hash to the constructor for the CipherKey.
Another way, but more costly in CPU time, is to use the RSAKey.createKeys(userName, password, bitLength) method to generate an RSA key-pair from a username/password pair. This can then be used to authenticate the user. It requires that the public key from the key-pair thus created be known to the server beforehand.
A: Call the flush() methods
The EncryptOFB, DecryptOFB, EncryptStream, DecryptStream and CipherStream classes all have close() methods which should be called before they are discarded. Amongst other things, they will terminate the threads used for pre-calculating the OFB key-streams.