java - Sending Strings Encoded by a secret key over TCP stream BadPaddingException with Windows -
i think i'm having problem specific windows operating system (windows 7) using writeutf() , readutf() methods sending encrypted strings on tcp connection.
the client , server first establish connection using private-public key pair. agree on shared key used further communications. problem occurs when strings encrypted shared key , sent via writeutf() , readutf() have bad padding. first instance when occurs when encrypted acknowledgement server client using writeutf() method sent.
the problem occurs sometimes! program runs smoothly through completion no errors, other times badpaddingexception thrown stating "given final block not padded" @ both client side:
byte[] bytedecriptedack = decryptcipher.dofinal(encryptedack.getbytes());
and server side:
byte[] bytedecriptedack = decryptcipher.dofinal(encryptedpassword.getbytes());
the problem not occur when running code on osx operating system. therefore, believe has how windows represents utf strings, writes utf strings or reads utf strings.
i'm @ loss trying fix problem. appreciated.
thanks
the code establishing connection client side:
private void establishconnection() { try { int numbytespubkey = in.readint(); byte[] bytespubkey = new byte[numbytespubkey]; in.readfully(bytespubkey, 0, numbytespubkey); //get public key server x509encodedkeyspec pubkeyspec = new x509encodedkeyspec(bytespubkey); keyfactory keyfactory = keyfactory.getinstance("rsa"); publickey pubkey = keyfactory.generatepublic(pubkeyspec); //generate secret key communicating keygenerator keygen = keygenerator.getinstance("aes"); keygen.init(128); //key size secretkey secretkey = keygen.generatekey(); byte[] encodedsecretkey = secretkey.getencoded(); //use public key encode message containing secret key send server encryptcipher = cipher.getinstance("rsa"); encryptcipher.init(cipher.encrypt_mode, pubkey); byte[] cipherdata = encryptcipher.dofinal(encodedsecretkey); //send secret key server encoded servers public key out.writeint(cipherdata.length); out.write(cipherdata, 0, cipherdata.length); //read acknowledge server secretkeyspec secretkeyspec = new secretkeyspec(encodedsecretkey,"aes"); string encryptedack = in.readutf(); decryptcipher = cipher.getinstance("aes"); decryptcipher.init(cipher.decrypt_mode, secretkeyspec); byte[] bytedecriptedack = decryptcipher.dofinal(encryptedack.getbytes()); if(!(new string(bytedecriptedack).equals("ack"))) { system.err.println("server acknowledgement corrupted. terminate communications."); system.exit(1); } //send password server encryptcipher = cipher.getinstance("aes"); encryptcipher.init(cipher.encrypt_mode, secretkeyspec); byte[] cipheredpassword = encryptcipher.dofinal("password".getbytes()); out.writeutf(new string(cipheredpassword)); } catch (exception e) { system.err.println(e.getmessage()); e.printstacktrace(); } }
the code establishing connection server side:
private void establishconnection() { try { //generate public/private key pair communicating keypairgenerator keygen = keypairgenerator.getinstance("rsa"); securerandom random = securerandom.getinstance("sha1prng", "sun"); keygen.initialize(1024, random); keypair pair = keygen.generatekeypair(); privatekey privkey = pair.getprivate(); publickey pubkey = pair.getpublic(); //send public key client byte[] bytespubkey = pubkey.getencoded(); out.writeint(bytespubkey.length); out.write(bytespubkey, 0, bytespubkey.length); //read in secret key use further communications int numbytessecretkey = in.readint(); byte[] bytessecretkey = new byte[numbytessecretkey]; in.readfully(bytessecretkey, 0, numbytessecretkey); decryptcipher = cipher.getinstance("rsa"); decryptcipher.init(cipher.decrypt_mode, privkey, decryptcipher.getparameters()); byte[] bytedecriptedsecretkey = decryptcipher.dofinal(bytessecretkey); secretkeyspec secretkeyspec = new secretkeyspec(bytedecriptedsecretkey,"aes"); //send acknowledgment encoded secret key: ack encryptcipher = cipher.getinstance("aes"); encryptcipher.init(cipher.encrypt_mode, secretkeyspec); byte[] cipheredack = encryptcipher.dofinal("ack".getbytes()); out.writeutf(new string(cipheredack)); //read password client string encryptedpassword = in.readutf(); decryptcipher = cipher.getinstance("aes"); decryptcipher.init(cipher.decrypt_mode, secretkeyspec); byte[] bytedecriptedack = decryptcipher.dofinal(encryptedpassword.getbytes()); if(!(new string(bytedecriptedack).equals("password"))) { system.err.println("access denied. client password incorrect. terminate communications."); system.exit(1); } else { system.err.println("access granted."); } } catch (exception e) { e.printstacktrace(); } }
byte[] cipheredack = encryptcipher.dofinal("ack".getbytes()); out.writeutf(new string(cipheredack));
that's not going work. utf , string character data. have raw bytes here, cannot interpreted text.
send them binary data:
out.write(cipheredack);
the reason see difference between os x , windows did not specify character encoding when coercing bytes string, becomes platform-specific. if character data, you'd pass character set constructor make platform-independent. in case, not character data anyway, go bytes.
also, why don't use ssl?
Comments
Post a Comment