java - Security: Write javax.mail.Message to File with Encryption -
i have 'javax.mail.message' object should written file system. use javax.mail (com.sun.mail) version 1.5.5
javax.mail.message message = buildmessage(...); message.writeto(new fileoutputstream("message.plain"));
now message written file. how can encrypt & decrypt file? post example below, code fails.
my example code:
static byte[] salt = new byte[8]; static { securerandom random = new securerandom(); random.nextbytes(salt); } public final void test() throws exception { message message = buildtestmessage(...); secretkey secret = encode(message, new fileoutputstream("test.encrypted"), "01234567".tochararray()); message message2 = decode(new fileinputstream("test.encrypted"), "01234567".tochararray()); // out sth. from@domain <--> null system.out.println(message.getfrom()[0] + " <--> " + message2.getfrom()); } private message decode( inputstream mailfileinputstream, char[] password) throws nosuchalgorithmexception, nosuchpaddingexception, invalidkeyexception, messagingexception, ioexception, invalidkeyspecexception { /* derive key, given password , salt. */ secretkeyfactory factory = secretkeyfactory.getinstance("pbewithhmacsha256andaes_128"); keyspec spec = new pbekeyspec(password, salt, 65536, 256); secretkey tmp = factory.generatesecret(spec); secretkey secret = new secretkeyspec(tmp.getencoded(), "pbewithhmacsha256andaes_128"); cipher cipher = cipher.getinstance("pbewithhmacsha256andaes_128"); cipher.init(cipher.decrypt_mode, secret); inputstream = new cipherinputstream(mailfileinputstream, cipher); properties props = new properties(); session session = session.getdefaultinstance(props, null); message message = new mimemessage(session, ); return message; } static secretkey encode( message message, fileoutputstream out, char[] password) throws exception { /* derive key, given password , salt. */ secretkeyfactory factory = secretkeyfactory.getinstance("pbewithhmacsha256andaes_128"); keyspec spec = new pbekeyspec(password, salt, 65536, 256); secretkey tmp = factory.generatesecret(spec); secretkey secret = new secretkeyspec(tmp.getencoded(), "pbewithhmacsha256andaes_128"); cipher cipher = cipher.getinstance("pbewithhmacsha256andaes_128"); cipher.init(cipher.encrypt_mode, secret); outputstream cos = new cipheroutputstream(out, cipher); message.writeto(cos); cos.close(); return secret; }
additional: upvote question , mark answer accepted. have question ban , no open questions left or no attention questions!
import java.io.bytearrayinputstream; import java.io.bytearrayoutputstream; import java.io.ioexception; import java.io.inputstream; import java.security.invalidalgorithmparameterexception; import java.security.invalidkeyexception; import java.security.nosuchalgorithmexception; import java.security.securerandom; import java.security.spec.invalidkeyspecexception; import java.security.spec.keyspec; import java.util.base64; import java.util.date; import java.util.optional; import javax.crypto.badpaddingexception; import javax.crypto.cipher; import javax.crypto.illegalblocksizeexception; import javax.crypto.nosuchpaddingexception; import javax.crypto.secretkey; import javax.crypto.secretkeyfactory; import javax.crypto.spec.ivparameterspec; import javax.crypto.spec.pbekeyspec; import javax.crypto.spec.secretkeyspec; import javax.mail.message; import javax.mail.messagingexception; import javax.mail.multipart; import javax.mail.session; import javax.mail.internet.internetaddress; import javax.mail.internet.mimebodypart; import javax.mail.internet.mimemessage; import javax.mail.internet.mimemultipart; public class stackoverflow { private static final int keysize = 128; static byte[] saltforthisrun = new byte[8]; static { securerandom random = new securerandom(); random.nextbytes(saltforthisrun); } public static void main( string[] args) throws exception { message message = buildtestmessage("from@null.org", new string[] { "to@null.org", "to2@null.org" }, "subject needed here", optional.of("this text"), optional.empty()); char[] password = "password".tochararray(); string encryptedmsg = encrypt(password, saltforthisrun, message); system.out.println("encryptedmsg: " + encryptedmsg); message message2 = decrypt(password, saltforthisrun, encryptedmsg); // out sth. from@domain <--> null system.out.println(message.getfrom()[0] + " <--> " + message2.getfrom()[0]); } private static message decrypt( char[] password, byte[] salt, string base64ciphertext) throws encryptionexception { try { secretkey secretkey = generatekey(password, salt, keysize); byte[] initializationvector = createinitializationvector(keysize); cipher aescipherfordecryption = cipher.getinstance("aes/cbc/pkcs5padding"); aescipherfordecryption.init(cipher.decrypt_mode, secretkey, new ivparameterspec(initializationvector)); byte[] decryptedbyteciphertext = base64.getdecoder().decode(base64ciphertext); byte[] bytedecryptedmessage = aescipherfordecryption.dofinal(decryptedbyteciphertext); return createmessagefrombytes(bytedecryptedmessage); } catch (illegalstateexception | invalidkeyexception | invalidalgorithmparameterexception | nosuchalgorithmexception | nosuchpaddingexception | invalidkeyspecexception | illegalblocksizeexception | badpaddingexception | messagingexception e) { throw new encryptionexception(string.format("unable enrypt message due to: %s", e.getmessage()), e); } } /** * * @param password * @param salt * @param message * @param chararray * @return base64 encoded ciphertext * @throws encryptionexception * if sth. goes wrong */ private static string encrypt( char[] password, byte[] salt, message message) throws encryptionexception { try { /** * step 1. generate aes key password , salt * */ secretkey secretkey = generatekey(password, salt, keysize); system.out.println(secretkey.getencoded().length); /** * step 2. generate initialization vector (iv) * a. use securerandom generate random bits * size of iv matches blocksize of cipher (e.g. 128 bits aes) * b. construct appropriate ivparameterspec object data pass cipher's init() method */ byte[] initializationvector = createinitializationvector(keysize); /** * step 3. create cipher specifying following parameters * a. algorithm name - here aes * b. mode - here cbc mode * c. padding - e.g. pkcs7 or pkcs5 * * must specify mode explicitly jce providers default ecb mode!! */ cipher aescipherforencryption = cipher.getinstance("aes/cbc/pkcs5padding"); /** * step 4. initialize cipher encryption */ aescipherforencryption.init(cipher.encrypt_mode, secretkey, new ivparameterspec(initializationvector)); /** * step 5. encrypt data * a. declare / initialize data. here data of type string * b. convert input text bytes * c. encrypt bytes using dofinal method */ byte[] byteciphertext = updatecipherwithmessage(aescipherforencryption, message); return new string(base64.getencoder().encode(byteciphertext)); } catch (illegalblocksizeexception | badpaddingexception | ioexception | messagingexception | invalidkeyexception | invalidalgorithmparameterexception | nosuchalgorithmexception | nosuchpaddingexception | invalidkeyspecexception e) { throw new encryptionexception(string.format("unable enrypt message due to: %s", e.getmessage()), e); } } private static mimemessage createmessagefrombytes( byte[] decodedbytes) throws messagingexception { inputstream = new bytearrayinputstream(decodedbytes); session session = null; return new mimemessage(session, is); } private static byte[] updatecipherwithmessage( cipher cipher, message message) throws ioexception, messagingexception, illegalblocksizeexception, badpaddingexception { bytearrayoutputstream os = new bytearrayoutputstream(); try { message.writeto(os); return cipher.dofinal(os.tobytearray()); } { os.close(); } } private static byte[] createinitializationvector( int keylength) { // save iv bytes or send in plaintext encrypted data can decrypt data later byte[] iv = new byte[keylength / 8]; securerandom prng = new securerandom(); prng.nextbytes(iv); return iv; } private static secretkey generatekey( char[] password, byte[] salt, int keysize) throws invalidkeyspecexception, nosuchalgorithmexception { int niterations = 65536; secretkeyfactory factory = secretkeyfactory.getinstance("pbkdf2withhmacsha1"); keyspec spec = new pbekeyspec(password, salt, niterations, keysize); secretkey tmp = factory.generatesecret(spec); return new secretkeyspec(tmp.getencoded(), "aes"); } private static message buildtestmessage( string from, string[] to, string subject, optional<string> text, optional<string> html) throws exception { string replyto = from; session session = null; message message = new mimemessage(session); multipart multipart = new mimemultipart("alternative"); try { if (text.ispresent()) { mimebodypart textpart = new mimebodypart(); textpart.settext(text.get(), "utf-8"); multipart.addbodypart(textpart); } if (html.ispresent()) { mimebodypart htmlpart = new mimebodypart(); htmlpart.setcontent(html, "text/html; charset=utf-8"); multipart.addbodypart(htmlpart); } message.setcontent(multipart); if (from != null) { message.setfrom(new internetaddress(from)); } else message.setfrom(); if (replyto != null) message.setreplyto(new internetaddress[] { new internetaddress(replyto) }); else message.setreplyto(new internetaddress[] { new internetaddress(from) }); internetaddress[] toaddresses = new internetaddress[to.length]; (int = 0; < toaddresses.length; i++) { toaddresses[i] = new internetaddress(to[i]); } message.setrecipients(message.recipienttype.to, toaddresses); message.setsubject(subject); message.setsentdate(new date()); return message; } catch (exception e) { e.printstacktrace(); system.out.println("exception: " + e.getmessage()); throw e; } } }
Comments
Post a Comment