diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj index c9bfeb22..bfe2f789 100644 --- a/src/babashka/impl/classes.clj +++ b/src/babashka/impl/classes.clj @@ -224,6 +224,7 @@ java.security.cert.X509Certificate java.security.cert.CertificateFactory javax.crypto.Cipher + javax.crypto.KeyAgreement javax.crypto.Mac javax.crypto.SecretKey javax.crypto.SecretKeyFactory @@ -407,14 +408,18 @@ java.nio.file.attribute.FileTime java.nio.file.attribute.PosixFilePermission java.nio.file.attribute.PosixFilePermissions]) - java.security.spec.PKCS8EncodedKeySpec - java.security.MessageDigest java.security.DigestInputStream - java.security.Provider java.security.KeyFactory + java.security.KeyPairGenerator + java.security.KeyPair java.security.KeyStore + java.security.MessageDigest + java.security.Provider java.security.SecureRandom java.security.Security + java.security.spec.ECGenParameterSpec + java.security.spec.PKCS8EncodedKeySpec + java.security.spec.X509EncodedKeySpec java.sql.Date java.text.ParseException java.text.ParsePosition @@ -776,6 +781,8 @@ java.security.cert.X509Certificate (instance? java.io.Console v) java.io.Console + (instance? java.security.KeyPairGenerator v) + java.security.KeyPairGenerator (instance? java.util.Set v) java.util.Set (instance? java.io.Closeable v) diff --git a/test/babashka/interop_test.clj b/test/babashka/interop_test.clj index b643a824..f43d66bb 100644 --- a/test/babashka/interop_test.clj +++ b/test/babashka/interop_test.clj @@ -48,6 +48,49 @@ (some? (.getSubjectX500Principal cert)) ")))) +(deftest ECDH-test + (is (true? (bb nil " +(import + '[java.security KeyPairGenerator MessageDigest] + '[java.security.spec ECGenParameterSpec] + '[javax.crypto KeyAgreement] + '[javax.crypto.spec SecretKeySpec]) + +(def keypair-algo \"EC\") +(def keypair-curve \"secp256r1\") +(def key-agreement-algo \"ECDH\") ; Elliptic Curve Diffie-Hellman +(def key-digest-algo \"SHA-256\") +(def key-encryption-algo \"AES\") + +(defn keypair + \"Generates a new key pair with the given alias, using the keypair-algo and keypair-curve\" + [] + (let [keygen (KeyPairGenerator/getInstance keypair-algo)] + (.initialize keygen (ECGenParameterSpec. keypair-curve)) + (.generateKeyPair keygen))) + +(defn symmetric-key + \"Generates a symmetric key using Elliptic Curve Diffie-Hellman based on a given local private and a remote public key\" + [private-key public-key] + ; Derive shared secret + (let [shared-secret + (let [key-agreement (KeyAgreement/getInstance key-agreement-algo)] + (.init key-agreement private-key) + (.doPhase key-agreement public-key true) + (.generateSecret key-agreement)) + symmetric-key + (let [message-digest (MessageDigest/getInstance key-digest-algo) + hash-bytes (.digest message-digest shared-secret) + key-bytes (byte-array (subvec (vec hash-bytes) 0 32))] ; extracts the first 256 bits for AES key + (SecretKeySpec. key-bytes key-encryption-algo))] + symmetric-key)) + +(let [[kp1 kp2] [(keypair) (keypair)] + [private public] [(.getPrivate kp1) (.getPublic kp2)] + symmetric (symmetric-key private public)] + (some? (.getAlgorithm symmetric))) +")))) + (deftest IntStream-test (is (pos? (bb nil "(.count (.codePoints \"woof🐕\"))"))))