使用 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上查看完整代码


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容

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