RSA使用文件中的PrivateKey进行签名

时间:2013-12-01 23:51:03

标签: haskell encryption rsa

使用Haskell,如何使用文件中的现有私钥进行签名?

在Python中,它就像 -

一样简单
import M2Crypto
rsa = M2Crypto.RSA.load_key("path/to/key")
result = rsa.sign("foo")

您似乎可以使用Codec.Crypto.RSA模块 -

进行签名

http://hackage.haskell.org/package/RSA-1.0.6.2/docs/Codec-Crypto-RSA.html#g:2

但我只看到如何从该模块生成新的私钥,而不是使用现有的私钥。似乎Network.TLS.Extra模块提供从文件中读取私钥 -

http://hackage.haskell.org/package/tls-extra-0.6.1/docs/Network-TLS-Extra.html#g:6

不幸的是,从每个模块导出的PrivateKey类型彼此不兼容 -

Couldn't match expected type `crypto-pubkey-types-0.4.0:Crypto.Types.PubKey.RSA.PrivateKey'
            with actual type `tls-1.1.5:Network.TLS.Crypto.PrivateKey'

2 个答案:

答案 0 :(得分:3)

使用HsOpenSSL似乎可以解决问题,而不是像python版本一样简短。

import OpenSSL.PEM
import OpenSSL.EVP.PKey
import OpenSSL.RSA
import Data.Maybe

main = do
    keyString <- readFile "/home/xxxxx/.ssh/id_rsa"
    key <- readPrivateKey keyString PwNone
    let maybeRsaKey = (toKeyPair key) :: Maybe RSAKeyPair
    let rsaKey = fromJust maybeRsaKey
    print  $ rsaD rsaKey

    -- Use Codec.Crypto.RSA module to sign 

答案 1 :(得分:3)

我需要类似的东西,所以我在前一段时间向包crypto-pubkey-openssh添加了一些序列化/反序列化。它不处理加密或ECC密钥,但足以满足大多数需求。

正如我的评论所说,你想要的是:

import Codec.Crypto.RSA (sign)
import Crypto.PubKey.OpenSsh (decodePrivate, OpenSshPrivateKey)
import Crypto.Types.PubKey.RSA (PrivateKey)
import Data.ByteString (ByteString)

throwLeft :: Either String OpenSshPrivateKey -> PrivateKey
throwLeft (Right (OpenSshPrivateKeyRsa k)) = k
throwLeft (Right _) = error "Wrong key type"
throwLeft (Left s)  = error $ "Error reading keys: " ++ s

readAndSign :: FilePath -> ByteString -> IO ByteString
readAndSign file msg = (flip sign msg . throwLeft . decodePrivate) `fmap` readFile file

请注意,此代码未经测试,但构建块应该是正确的。您想要使用私钥(readFiledecodePrivate)进行阅读。执行一些错误检查(throwLeft)并签署消息(sign)。

编辑: 我觉得识别问题的方式比问题中的Python示例更长。看起来好像构建块是相同的,但库中公开的抽象级别与错误处理(显式与异常)非常不同。如果我们假设库作者通过从一个模块重新导出所有内容并定义了一个帮助程序来做更多的工作:

loadKey :: FilePath -> IO PrivateKey
loadKey p = (throwLeft . decodePrivate) `fmap` readFile p

然后代码几乎相同:

k <-loadKey keyFile
let result = sign k msg