使用 Clojure 以及 Java 安全库,实现 PGP 主流程

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)))

在github上查看完整代码


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 首先罗列一些知识点: 1.加密算法通常分为对称性加密算法和非对称性加密算法:对于对称性加密算法,信息接收双方都需事...
    JonesCxy阅读 5,282评论 2 4
  • 随着对于安全度的不断要求,对于数据加解密与破解之间的斗争,加解密的方式也在不断发生着变化,来看看现在流行的一些加解...
    zhouhao_180阅读 6,401评论 1 12
  • 服务器通常要处理三类事件:IO事件、信号事件、定时事件。由此产生了两种事件处理模式: Reactor模式:同步IO...
    翼动晴空阅读 4,649评论 0 4
  • 一直有所期待,从未想过放弃。 当你决心想去做某件事时,全世界都会帮你,如何让自己真正的改变?怎样才能拥一颗真正改变...
    芳芳郁金香_1e19阅读 1,761评论 4 8
  • 是否该选择行路匆匆 背离的才痛快告别 祈祷声起,从过去快些走过 特别那些痛苦的 变成想念的财富 亦或一首深沉的诗,...
    木方山阅读 1,254评论 0 0