使用 Clojure 以及 Java 安全库,实现 PGP 主流
2016-05-14 本文已影响206人
BlindingDark
PGP
Clojure
主要函数:
- 使用 MD5 计算文件的特征值
(defn md5-result
"获取hash序列,参数为file类型,返回hash的byte数组"
[file]
(let [md5 (MessageDigest/getInstance "MD5")]
(.update md5 (.getBytes (slurp file) "utf-8"))
(.digest md5)))
- BASE64 编/解码
;BASE64编码
(defn BASE64-encoder
"参数是要编码的byte数组,返回String"
[file-byte]
(.encodeBuffer (BASE64Encoder.) file-byte))
;BASE64解码
(defn BASE64-decoder
"参数是要解码的file-string,返回解码后的byte"
[file-string]
(.decodeBuffer (BASE64Decoder.) file-string))
- 生成 RSA 公钥-私钥对
;生成公钥和私钥对,基于RSA算法
(defn generate-RSA-key-pair
"生成公钥和私钥对,RSA算法,无参数,返回公钥-私钥对"
[]
(let [key-pair-gen (KeyPairGenerator/getInstance "RSA")]
(.initialize key-pair-gen 1024)
(let [key-pair (.generateKeyPair key-pair-gen)]
(.getPublic key-pair)
(map #(BASE64-encoder (.getEncoded %))
[(.getPublic key-pair) (.getPrivate key-pair)]))))
- 由字符串还原公钥-私钥对
(defn get-private-key-ob
"得到private-key的对象,参数是私钥字符串"
[private-key]
(let [keyFactory (KeyFactory/getInstance "RSA")]
(.generatePrivate
keyFactory
(PKCS8EncodedKeySpec. (BASE64-decoder private-key)))))
(defn get-public-key-ob
"得到public-key的对象,参数是公钥字符串"
[public-key]
(let [keyFactory (KeyFactory/getInstance "RSA")]
(.generatePublic
keyFactory
(X509EncodedKeySpec. (BASE64-decoder public-key)))))
- 生成 DES 密钥
(defn generate-DES-key
"参数为密钥字符串,返回值为DES密钥key对象"
[string-key]
(let [key-gen (KeyGenerator/getInstance "DESede")]
(.init key-gen (SecureRandom. (.getBytes string-key)))
(.generateKey key-gen)))
- 加/解密函数
(defn encrypt
"加密byte数组,第一个参数是算法名字符表示,第二个参数是key,第三个参数是要加密的byte数组"
[algorithm some-key some-byte]
(let [cipher (Cipher/getInstance algorithm)]
(.init cipher Cipher/ENCRYPT_MODE some-key)
(.doFinal cipher some-byte)))
(defn decrypt
"解密byte数组,第一个参数是算法名字符表示,第二个参数是key,第三个参数是要解密的byte数组"
[algorithm some-key some-byte]
(let [cipher (Cipher/getInstance algorithm)]
(.init cipher Cipher/DECRYPT_MODE some-key)
(.doFinal cipher some-byte)))
主程序流程:
- 发送方
;创建hash文件。base64编码再保存,file-mail为mail文件,file-hash为摘要文件
(creat-hash-file file-mail file-hash)
;RSA加密(签名)hash文件;用私钥加密(签名)hash文件
(spit
file-signed-hash
(RSA-encrypt-by-private-key
(slurp file-private)
(slurp file-hash)))
;压缩
(zip-2-files file-hash-mail-zip file-mail file-signed-hash)
;zip编码base64,保存为txt
(spit
file-hash-mail-BASE64ed
(BASE64-encoder
(FileUtils/readFileToByteArray file-hash-mail-zip)))
;一次性密钥加密
(let [DES-key (generate-random-DES-key)]
(spit file-hash-mail-encrypted
(DES-encrypt-string
(second DES-key)
(slurp file-hash-mail-BASE64ed)))
(spit file-DES-key (first DES-key)))
;用公钥对DES-key加密(保密)
(spit
file-DES-key-encrypted
(RSA-encrypt-by-public-key
(slurp file-public)
(slurp file-DES-key)))
;压缩
(zip-2-files
file-mail-ready-zip
file-hash-mail-encrypted
file-DES-key-encrypted)
;zip编码base64,保存为txt
(spit
file-send
(BASE64-encoder
(FileUtils/readFileToByteArray file-mail-ready-zip)))
- 接收方
;解码发来的Email
(copy (BASE64-decoder (slurp file-receive)) file-mail-zip)
;解压
(unzip file-mail-zip (.getParent file-mail-zip))
;用私钥解密DES-key
(spit
file-DES-key-rec
(RSA-decrypt-by-private-key
(slurp file-private)
(slurp file-DES-key-encrypted-rec)))
;用一次性密钥解密
(spit
file-hash-mail-BASE64ed-rec
(DES-decrypt-string
(generate-DES-key
(slurp file-DES-key-rec))
(slurp file-hash-mail-encrypted-rec)))
;解码zip的base64
(copy
(BASE64-decoder
(slurp file-hash-mail-BASE64ed-rec))
file-hash-mail-zip-rec)
;解压
(unzip
file-hash-mail-zip-rec
(.getParent file-hash-mail-zip-rec))
;判断是否是本人
(=
;计算hash
(BASE64-encoder (md5-result file-mail-rec))
;用对方公钥解密signed-hash
(RSA-decrypt-by-public-key
(slurp file-public)
(slurp file-signed-hash-rec)))