Skip to content

Instantly share code, notes, and snippets.

@mangosmoothie
Last active May 6, 2020 19:15
Show Gist options
  • Save mangosmoothie/65aa8c0b0818c1ff0a5c8128661529ab to your computer and use it in GitHub Desktop.
Save mangosmoothie/65aa8c0b0818c1ff0a5c8128661529ab to your computer and use it in GitHub Desktop.
crypto with clojure using RSA asymmetric keys
;; https://blog.jonm.dev/posts/rsa-public-key-cryptography-in-java/
;; generate a 2048-bit RSA private key
;; $ openssl genrsa -out private_key.pem 2048
;; # convert private Key to PKCS#8 format (so Java can read it)
;; $ openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem \
;; -out private_key.der -nocrypt
;; # output public key portion in DER format (so Java can read it)
;; $ openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
(ns crypto
(:require
[clojure.java.io :as io])
(:import
java.io.DataInputStream
java.security.Key
java.security.KeyFactory
java.security.spec.PKCS8EncodedKeySpec
java.security.spec.X509EncodedKeySpec
java.util.Base64
javax.crypto.Cipher
javax.crypto.KeyGenerator
javax.crypto.SecretKey))
(def RSA-TRANSFORM "RSA/ECB/PKCS1Padding")
(defn- apply-cipher [^bytes b ^Key k ^Integer mode ^String transformation]
(let [c (Cipher/getInstance transformation)]
(.init c mode k)
(.doFinal c b)))
(defn decrypt-bytes
"returns decrypted byte array"
[^bytes b ^Key key ^String transformation]
(apply-cipher b key Cipher/DECRYPT_MODE transformation))
(defn encrypt-bytes
"returns encrypted byte array"
[^bytes b ^Key key ^String transformation]
(apply-cipher b key Cipher/ENCRYPT_MODE transformation))
(defn decrypt-rsa
"decrypt base64 encoded string representation of RSA encrypted byte array"
[^String s ^Key rsa-private-key]
(String.
(decrypt-bytes (.decode (Base64/getDecoder) s) rsa-private-key RSA-TRANSFORM)))
(defn encrypt-rsa
"encrypt string with RSA and return base64 encoded string representation"
[^String s ^Key rsa-private-key]
(.encodeToString (Base64/getEncoder)
(encrypt-bytes (.getBytes s) rsa-private-key RSA-TRANSFORM)))
(defn- read-file-to-byte-array
[file]
(let [file (io/as-file file)
result (byte-array (.length file))]
(with-open [in (DataInputStream. (io/input-stream file))]
(.readFully in result))
result))
(defn get-private-key
"
get private key from RSA binary DER/ASN.1 BER encoded file
file arg can be string path (relative or absolute) or file instance
"
[file]
(let [kf (KeyFactory/getInstance "RSA")]
(.generatePrivate
kf
(PKCS8EncodedKeySpec. (read-file-to-byte-array file)))))
(defn get-public-key
"
get public key from RSA binary DER/ASN.1 BER encoded file
file arg can be string path (relative or absolute) or file instance
"
[file]
(let [kf (KeyFactory/getInstance "RSA")]
(.generatePublic
kf
(X509EncodedKeySpec. (read-file-to-byte-array file)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment