Last active
May 6, 2020 19:15
-
-
Save mangosmoothie/65aa8c0b0818c1ff0a5c8128661529ab to your computer and use it in GitHub Desktop.
crypto with clojure using RSA asymmetric keys
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; 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