Alice would like to send a large file to Bob without disclosing the content of the file to anybody else. Alice also would like to make sure no other people can modify the message without being noticed. Unfortunately, Alice doesn’t share any secret key with Bob. The good news is that Alice and Bob know each other’s RSA public key. Assume Alice’s RSA private key is SKA, and her public key is PKA. Similarly, Bob’s RSA private key is SKB, and his public key is PKB.
We have developed a solution described in the class slides TO5.2_PublicKey_Crypto (31-33) . Your job is to develop a software tool that implements this solution for Alice and Bob.
java FEA genkey
java FEA send [sender_private_key] [receiver_public_key] [plaintext file] [ciphertext file]
Your program should read the sender's private key stored in [sender_private_key] file, read the receiver's public key in [receiver_public_key] file, then encrypt and sign the [plaintext file] file, and finally save the result in a file named [ciphertext file]. You should use SHA-1 as the hash function before signing. You may specify this by providing a parameter "SHA1withRSA" to the Signature class, or hash it by yourself and then generate the signature. Note that the four file names are all provided by the user.
The output file should store E_{PKB}(Ks||IV) || E_{Ks}(F) || Sig_{SKA} (E_PKB(Ks||IV) || E_Ks(F)) in the exact order. The encryption of file F (i.e., E_{Ks}(F)) should be done with AES-128 in CBC mode with PKCS5Padding, where the encryption key is Ks and the initialization vector is IV. Logically, the output file consists of three components: The encrypted session key and IV E_{PKB}(Ks||IV), the encrypted file E_{Ks}(F), and the signature Sig_{SKA} (E_PKB(Ks||IV) || E_Ks(F)). When you store these components in file, each component should start with a 4 byte length fields indicating the number of bytes in this component (excluding the length field), with the remaining part stores the most significant byte first. As a result, the receiver can parse these components and read them into memory. For interoperability purposes, let us decide that the signature is generated over the concatenation of E_{PKB}(Ks||IV) and E_{Ks}(F) without the length field.
java FEA receive [receiver_private_key] [sender_public_key] [ciphertext file] [plaintext file]
Your program should read receiver's private key from the [receiver_private_key] file, read the sender's public key from [sender_public_key] file, then verify and decrypt the [ciphertext file] file, and finally save the recovered file in plaintext in a file named [plaintext file].
If the signature is valid, your program should display a message showing "Signature successfully verified..." and continue the operations described above. Before exiting, your program should print out the SHA-1 hash of the decrypted (i.e., original) file in Hexdecimal. Use all upper case letters for hexdecimal 'A' through 'F'. You may reuse your conversion function you wrote for HW#2.
However, if the signature is invalid, your program should display "Signature is invalid. The [ciphertext file] may have been modified or forged...", and then exit.