44import java .util .Arrays ;
55import java .util .Random ;
66import java .net .*;
7+ import java .nio .ByteBuffer ;
78import java .security .KeyFactory ;
89import java .security .NoSuchAlgorithmException ;
10+ import java .security .InvalidAlgorithmParameterException ;
911import java .security .InvalidKeyException ;
1012import java .security .PublicKey ;
1113import java .security .PrivateKey ;
14+ import java .security .SecureRandom ;
1215import java .security .Signature ;
1316import java .security .SignatureException ;
1417import java .security .spec .EdECPoint ;
1720import java .security .spec .NamedParameterSpec ;
1821import java .security .spec .EdECPrivateKeySpec ;
1922import java .security .spec .PKCS8EncodedKeySpec ;
20- import javax .crypto .spec .SecretKeySpec ;
2123import java .security .spec .X509EncodedKeySpec ;
2224import java .io .IOException ;
25+ import java .util .Scanner ;
26+ import javax .crypto .Cipher ;
27+ import javax .crypto .BadPaddingException ;
28+ import javax .crypto .IllegalBlockSizeException ;
29+ import javax .crypto .NoSuchPaddingException ;
30+ import javax .crypto .SecretKey ;
31+ import javax .crypto .spec .IvParameterSpec ;
32+ import javax .crypto .spec .SecretKeySpec ;
2333// import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
2434// import org.bouncycastle.crypto.Signer;
2535// import org.bouncycastle.crypto.signers.Ed25519Signer;
@@ -329,7 +339,7 @@ private boolean longInRange(long value) {
329339 return true ;
330340 }
331341
332- private byte [] uint32ToBytes (long value ) {
342+ public byte [] uint32ToBytes (long value ) {
333343 if (!longInRange (value )) {
334344 return null ;
335345 }
@@ -341,7 +351,7 @@ private byte[] uint32ToBytes(long value) {
341351 };
342352 }
343353
344- private long bytesToUint32 (byte [] data ) {
354+ public long bytesToUint32 (byte [] data ) {
345355 if (data == null || data .length != 4 ) {
346356 return -1 ;
347357 }
@@ -359,4 +369,79 @@ public void notMatchY() {
359369 public void success (byte [] sharedSecret ) {
360370 System .out .println ("Initiator & responder agreed on shared secret " + convertToHex (sharedSecret ));
361371 }
372+
373+ private static final String ENCRYPT_ALGO = "ChaCha20-Poly1305" ;
374+ private static final int NONCE_LEN = 12 ;
375+ public byte [] encrypt (byte [] plaintext , byte [] key ) {
376+ Cipher cipher ;
377+ try {
378+ cipher = Cipher .getInstance (ENCRYPT_ALGO );
379+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e ) {
380+ return null ;
381+ }
382+
383+ byte [] nonce = new byte [NONCE_LEN ];
384+ new SecureRandom ().nextBytes (nonce );
385+
386+ // IV, initialization value with nonce
387+ IvParameterSpec iv = new IvParameterSpec (nonce );
388+
389+ SecretKey keyObject = new SecretKeySpec (key , "AES" );
390+ try {
391+ cipher .init (Cipher .ENCRYPT_MODE , keyObject , iv );
392+ } catch (InvalidKeyException | InvalidAlgorithmParameterException e ) {
393+ return null ;
394+ }
395+
396+ byte [] encryptedText ;
397+ try {
398+ encryptedText = cipher .doFinal (plaintext );
399+ } catch (IllegalBlockSizeException | BadPaddingException e ) {
400+ return null ;
401+ }
402+
403+ // prepend nonce to the encrypted text
404+ byte [] output = ByteBuffer .allocate (encryptedText .length + NONCE_LEN )
405+ .put (nonce )
406+ .put (encryptedText )
407+ .array ();
408+
409+ return output ;
410+ }
411+
412+ public byte [] decrypt (byte [] ciphertext , byte [] key ) {
413+ ByteBuffer bb = ByteBuffer .wrap (ciphertext );
414+
415+ // split ciphertext to get the prepended nonce
416+ byte [] nonce = new byte [NONCE_LEN ];
417+ byte [] encryptedText = new byte [ciphertext .length - NONCE_LEN ];
418+ bb .get (nonce );
419+ bb .get (encryptedText );
420+
421+ Cipher cipher ;
422+ try {
423+ cipher = Cipher .getInstance (ENCRYPT_ALGO );
424+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e ) {
425+ System .out .println (e );
426+ return null ;
427+ }
428+
429+ IvParameterSpec iv = new IvParameterSpec (nonce );
430+
431+ SecretKey keyObject = new SecretKeySpec (key , "AES" );
432+ try {
433+ cipher .init (Cipher .DECRYPT_MODE , keyObject , iv );
434+ } catch (InvalidKeyException | InvalidAlgorithmParameterException e ) {
435+ System .out .println (e );
436+ return null ;
437+ }
438+
439+ // decrypted text
440+ try {
441+ return cipher .doFinal (encryptedText );
442+ } catch (IllegalBlockSizeException | BadPaddingException e ) {
443+ System .out .println (e );
444+ return null ;
445+ }
446+ }
362447}
0 commit comments