// Sample encryption and decryption in Frink using Java's cryptographic // libraries. // // This is based on this posting: // // http://stackoverflow.com/questions/992019/java-256-bit-aes-password-based-encryption // // Also, to turn this into an AEAD algorithm like AES-GCM, see maybe: // https://javainterviewpoint.com/java-aes-256-gcm-encryption-and-decryption/ // // By the way, if you want to do AES-256 encryption, you need to enable // stronger encryption by downloading a policy file for Java. (Crypto // strength is limited by default due to export restrictions. 128-bit // encryption may work out of the box. If you get an error that says // something about "Illegal key length", then you probably don't have the // unlimited cryptography policy file installed. // // You can download it from here: // http://tinyurl.com/355cx3m // And go to the bottom of the page and download "Java Cryptography // Extension (JCE) Unlimited Strength Jurisdiction Policy Files". Inside // that zip file there are instructions for installing them to the right // place. // (On Fedora with OpenJDK, it was /usr/java/jdk1.7.0_03/jre/lib/security // but this path will change with each release. Sigh.) password = input["Enter password: "] // You'll need a way to transmit this salt to the receiver. It doesn't need // to be kept secret, but does protect against dictionary attacks on your // password. salt = randomBytes[32] println["Randomly-generated salt is: "] for i=salt print[padLeft[base[i, 16],2,"0"] + " "] println[] // Now turn the password into an array of chars. pwchars = newJavaArray["char",length[password]] newJava["java.lang.String",password].getChars[0,length[password],pwchars,0] // Create a Secret Key Factory factory = callJava["javax.crypto.SecretKeyFactory", "getInstance", ["PBKDF2WithHmacSHA256"]] // Create the secret key. This performs 256-bit AES. You can change the // 256 to 128 if you don't have the unlimited strength crypto files. // The 65536 is the iteration count. keyspec = newJava["javax.crypto.spec.PBEKeySpec", [pwchars, salt, 65536, 256]] tmp = factory.generateSecret[keyspec] secret = newJava["javax.crypto.spec.SecretKeySpec", [tmp.getEncoded[], "AES"]] // Algorithms like HTTPS exchange the secret key by a process like // Diffie-Hellman key exchange. Programs like gpg use something like // public-key RSA encryption to exchange encrypted secret keys, which are then // used to initialize the AES encryption which is used to encrypt the body of // the message. // constructor for AES encryption with proper padding. cipher=callJava["javax.crypto.Cipher","getInstance", ["AES/CBC/PKCS5Padding"]] // text to be encrypted text = "Frink rocks (or whatever you want to encrypt). \u263a" // Convert the plaintext to an array of bytes using the specified encoding. plaintextBytes = stringToBytes[text, "UTF-8"] // Perform encryption cipher.init[cipher.ENCRYPT_MODE, secret] // set encryption mode (1) params = cipher.getParameters[] // Get initialization vector. ivClass = callJava["java.lang.Class", "forName", ["javax.crypto.spec.IvParameterSpec"]] iv = params.getParameterSpec[ivClass].getIV[] ciphertext = cipher.doFinal[plaintextBytes] // Perform the actual encryption // Returns a Java array of bytes. // Dump the encrypted text as hex bytes. println["\nEncrypted text:"] for i = ciphertext print[padLeft[base[i, 16],2,"0"]] println[] println[] // Decrypt ivparam = newJava["javax.crypto.spec.IvParameterSpec", [iv]] cipher.init[cipher.DECRYPT_MODE, secret, ivparam] // set decryption mode (2), same key plaintext = cipher.doFinal[ciphertext] println["Decrypted text:"] // Create a Unicode string from the bytes and specified encoding. println[bytesToString[plaintext, "UTF-8"]]