-- | Deal with details related to the structural layout of an SDMF share.
module Tahoe.SDMF.Internal.Share where

import Control.Monad (unless)
import Crypto.Cipher.Types (makeIV)
import qualified Crypto.PubKey.RSA.Types as RSA
import Data.ASN1.BinaryEncoding (DER (DER))
import Data.ASN1.Encoding (ASN1Encoding (encodeASN1), decodeASN1')
import Data.ASN1.Types (ASN1Object (fromASN1, toASN1))
import Data.Binary (Binary (..), Get, getWord8)
import Data.Binary.Get (bytesRead, getByteString, getLazyByteString, getRemainingLazyByteString, getWord16be, getWord32be, getWord64be, isEmpty, isolate)
import Data.Binary.Put (putByteString, putLazyByteString, putWord16be, putWord32be, putWord64be, putWord8)
import qualified Data.ByteArray as ByteArray
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB
import Data.Int (Int64)
import Data.Word (Word16, Word32, Word64, Word8)
import Data.X509 (PrivKey (PrivKeyRSA), PubKey (PubKeyRSA))
import Tahoe.CHK.Merkle (MerkleTree, leafHashes)
import Tahoe.CHK.SHA256d (Digest' (Digest'), SHA256d, toBytes)
import Tahoe.SDMF.Internal.Converting (From (from), into, tryInto)
import qualified Tahoe.SDMF.Internal.Keys as Keys

hashSize :: Int
hashSize :: Int
hashSize = Int
32

newtype HashChain = HashChain
    { HashChain -> [(Word16, ByteString)]
hashChain :: [(Word16, B.ByteString)]
    }
    deriving newtype (HashChain -> HashChain -> Bool
(HashChain -> HashChain -> Bool)
-> (HashChain -> HashChain -> Bool) -> Eq HashChain
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HashChain -> HashChain -> Bool
$c/= :: HashChain -> HashChain -> Bool
== :: HashChain -> HashChain -> Bool
$c== :: HashChain -> HashChain -> Bool
Eq, Int -> HashChain -> ShowS
[HashChain] -> ShowS
HashChain -> String
(Int -> HashChain -> ShowS)
-> (HashChain -> String)
-> ([HashChain] -> ShowS)
-> Show HashChain
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HashChain] -> ShowS
$cshowList :: [HashChain] -> ShowS
show :: HashChain -> String
$cshow :: HashChain -> String
showsPrec :: Int -> HashChain -> ShowS
$cshowsPrec :: Int -> HashChain -> ShowS
Show, b -> HashChain -> HashChain
NonEmpty HashChain -> HashChain
HashChain -> HashChain -> HashChain
(HashChain -> HashChain -> HashChain)
-> (NonEmpty HashChain -> HashChain)
-> (forall b. Integral b => b -> HashChain -> HashChain)
-> Semigroup HashChain
forall b. Integral b => b -> HashChain -> HashChain
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> HashChain -> HashChain
$cstimes :: forall b. Integral b => b -> HashChain -> HashChain
sconcat :: NonEmpty HashChain -> HashChain
$csconcat :: NonEmpty HashChain -> HashChain
<> :: HashChain -> HashChain -> HashChain
$c<> :: HashChain -> HashChain -> HashChain
Semigroup)

instance Binary HashChain where
    put :: HashChain -> Put
put (HashChain []) = Put
forall a. Monoid a => a
mempty
    put (HashChain ((Word16
n, ByteString
h) : [(Word16, ByteString)]
c)) = do
        Word16 -> Put
putWord16be Word16
n
        ByteString -> Put
putByteString ByteString
h
        HashChain -> Put
forall t. Binary t => t -> Put
put ([(Word16, ByteString)] -> HashChain
HashChain [(Word16, ByteString)]
c)

    get :: Get HashChain
get = do
        Bool
empty <- Get Bool
isEmpty
        if Bool
empty
            then HashChain -> Get HashChain
forall (f :: * -> *) a. Applicative f => a -> f a
pure (HashChain -> Get HashChain) -> HashChain -> Get HashChain
forall a b. (a -> b) -> a -> b
$ [(Word16, ByteString)] -> HashChain
HashChain []
            else do
                Word16
n <- Get Word16
getWord16be
                ByteString
h <- Int -> Get ByteString
getByteString Int
hashSize
                ([(Word16, ByteString)] -> HashChain
HashChain [(Word16
n, ByteString
h)] HashChain -> HashChain -> HashChain
forall a. Semigroup a => a -> a -> a
<>) (HashChain -> HashChain) -> Get HashChain -> Get HashChain
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get HashChain
forall t. Binary t => Get t
get

{- | Structured representation of a single version SDMF share.

 See Tahoe-LAFS "mutable" specification document, section title "SDMF Slot
 Format".

 Since the only version of SDMF that is specified uses version 0, this
 implicitly represents a version 0 SDMF.  If new versions of SDMF are
 specified then new constructors may be added.
-}
data Share = Share
    { -- | sequence number. 2^64-1 must be handled specially, TBD
      Share -> Word64
shareSequenceNumber :: Word64
    , -- | "R" (root of share hash merkle tree)
      Share -> ByteString
shareRootHash :: B.ByteString
    , -- | The IV for encryption of share data.
      Share -> SDMF_IV
shareIV :: Keys.SDMF_IV
    , -- | The total number of encoded shares (k).
      Share -> Word8
shareTotalShares :: Word8
    , -- | The number of shares required for decoding (N).
      Share -> Word8
shareRequiredShares :: Word8
    , -- | The size of a single ciphertext segment.  This differs from
      -- shareDataLength in that it includes padding.
      Share -> Word64
shareSegmentSize :: Word64
    , -- | The length of the original plaintext.
      Share -> Word64
shareDataLength :: Word64
    , -- | The 2048 bit "verification" RSA key.
      Share -> Verification
shareVerificationKey :: Keys.Verification
    , -- | The RSA signature of
      -- H('\x00'+shareSequenceNumber+shareRootHash+shareIV+encoding
      -- parameters) where '\x00' gives the version of this share format (0)
      -- and the encoding parameters are a certain serialization of
      -- shareRequiredShares and shareTotalShares.
      Share -> ByteString
shareSignature :: B.ByteString
    , -- | The share numbers and shareRootHash values which are required to
      -- ... something about verification I dunno. XXX
      Share -> HashChain
shareHashChain :: HashChain
    , -- | A merkle tree where leaves are the hashes of the blocks in this share.
      Share -> MerkleTree ByteString SHA256d
shareBlockHashTree :: MerkleTree B.ByteString SHA256d
    , -- | The share data (erasure encoded ciphertext).
      Share -> ByteString
shareData :: LB.ByteString
    , -- | The encrypted 2048 bit "signature" RSA key.
      Share -> ByteString
shareEncryptedPrivateKey :: B.ByteString
    }
    deriving (Share -> Share -> Bool
(Share -> Share -> Bool) -> (Share -> Share -> Bool) -> Eq Share
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Share -> Share -> Bool
$c/= :: Share -> Share -> Bool
== :: Share -> Share -> Bool
$c== :: Share -> Share -> Bool
Eq, Int -> Share -> ShowS
[Share] -> ShowS
Share -> String
(Int -> Share -> ShowS)
-> (Share -> String) -> ([Share] -> ShowS) -> Show Share
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Share] -> ShowS
$cshowList :: [Share] -> ShowS
show :: Share -> String
$cshow :: Share -> String
showsPrec :: Int -> Share -> ShowS
$cshowsPrec :: Int -> Share -> ShowS
Show)

instance Binary Share where
    put :: Share -> Put
put Share{Word8
Word64
ByteString
ByteString
MerkleTree ByteString SHA256d
SDMF_IV
Verification
HashChain
shareEncryptedPrivateKey :: ByteString
shareData :: ByteString
shareBlockHashTree :: MerkleTree ByteString SHA256d
shareHashChain :: HashChain
shareSignature :: ByteString
shareVerificationKey :: Verification
shareDataLength :: Word64
shareSegmentSize :: Word64
shareRequiredShares :: Word8
shareTotalShares :: Word8
shareIV :: SDMF_IV
shareRootHash :: ByteString
shareSequenceNumber :: Word64
shareEncryptedPrivateKey :: Share -> ByteString
shareData :: Share -> ByteString
shareBlockHashTree :: Share -> MerkleTree ByteString SHA256d
shareHashChain :: Share -> HashChain
shareSignature :: Share -> ByteString
shareVerificationKey :: Share -> Verification
shareDataLength :: Share -> Word64
shareSegmentSize :: Share -> Word64
shareRequiredShares :: Share -> Word8
shareTotalShares :: Share -> Word8
shareIV :: Share -> SDMF_IV
shareRootHash :: Share -> ByteString
shareSequenceNumber :: Share -> Word64
..} = do
        Word8 -> Put
putWord8 Word8
0
        Word64 -> Put
putWord64be Word64
shareSequenceNumber
        ByteString -> Put
putByteString ByteString
shareRootHash
        ByteString -> Put
putByteString (ByteString -> Put) -> (SDMF_IV -> ByteString) -> SDMF_IV -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SDMF_IV -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
ByteArray.convert (SDMF_IV -> Put) -> SDMF_IV -> Put
forall a b. (a -> b) -> a -> b
$ SDMF_IV
shareIV
        Word8 -> Put
putWord8 Word8
shareRequiredShares
        Word8 -> Put
putWord8 Word8
shareTotalShares
        Word64 -> Put
putWord64be Word64
shareSegmentSize
        Word64 -> Put
putWord64be Word64
shareDataLength
        Word32 -> Put
putWord32be Word32
signatureOffset
        Word32 -> Put
putWord32be Word32
hashChainOffset
        Word32 -> Put
putWord32be Word32
blockHashTreeOffset
        Word32 -> Put
putWord32be Word32
shareDataOffset
        Word64 -> Put
putWord64be Word64
encryptedPrivateKeyOffset
        Word64 -> Put
putWord64be Word64
eofOffset
        ByteString -> Put
putByteString ByteString
verificationKeyBytes
        ByteString -> Put
putByteString ByteString
shareSignature
        HashChain -> Put
forall t. Binary t => t -> Put
put HashChain
shareHashChain
        MerkleTree ByteString SHA256d -> Put
forall t. Binary t => t -> Put
put MerkleTree ByteString SHA256d
shareBlockHashTree
        ByteString -> Put
putLazyByteString ByteString
shareData
        ByteString -> Put
putByteString ByteString
shareEncryptedPrivateKey
      where
        verificationKeyBytes :: ByteString
verificationKeyBytes = Verification -> ByteString
Keys.verificationKeyToBytes Verification
shareVerificationKey
        blockHashTreeBytes :: ByteString
blockHashTreeBytes = [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (MerkleTree ByteString SHA256d -> [ByteString])
-> MerkleTree ByteString SHA256d
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Digest' SHA256d -> ByteString)
-> [Digest' SHA256d] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Digest' SHA256d -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
toBytes ([Digest' SHA256d] -> [ByteString])
-> (MerkleTree ByteString SHA256d -> [Digest' SHA256d])
-> MerkleTree ByteString SHA256d
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MerkleTree ByteString SHA256d -> [Digest' SHA256d]
forall v a. MerkleTree v a -> [Digest' a]
leafHashes (MerkleTree ByteString SHA256d -> ByteString)
-> MerkleTree ByteString SHA256d -> ByteString
forall a b. (a -> b) -> a -> b
$ MerkleTree ByteString SHA256d
shareBlockHashTree

        -- Some conversions could fail because we can't be completely sure of
        -- the size of the data we're working with.  Put has no good failure
        -- mechanism though.  Try to provide the best failure behavior we can
        -- here.
        signatureOffset :: Word32
signatureOffset =
            case String -> Int -> Maybe Word32
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word32 String
"" (Int -> Maybe Word32) -> Int -> Maybe Word32
forall a b. (a -> b) -> a -> b
$ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
hashSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
16 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
18 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
32 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteString -> Int
B.length ByteString
verificationKeyBytes of
                Maybe Word32
Nothing -> String -> Word32
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent signature offset"
                Just Word32
x -> Word32
x

        hashChainOffset :: Word32
hashChainOffset =
            Word32
signatureOffset
                Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ case String -> Int -> Maybe Word32
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word32 String
"" (ByteString -> Int
B.length ByteString
shareSignature) of
                    Maybe Word32
Nothing -> String -> Word32
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent hash chain offset"
                    Just Word32
x -> Word32
x
        blockHashTreeOffset :: Word32
blockHashTreeOffset =
            Word32
hashChainOffset
                Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ case String -> Int -> Maybe Word32
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word32 String
"" ([(Word16, ByteString)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (HashChain -> [(Word16, ByteString)]
hashChain HashChain
shareHashChain) Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
hashSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2)) of
                    Maybe Word32
Nothing -> String -> Word32
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent block hash tree offset"
                    Just Word32
x -> Word32
x
        shareDataOffset :: Word32
shareDataOffset =
            Word32
blockHashTreeOffset
                Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ case String -> Int -> Maybe Word32
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word32 String
"" (ByteString -> Int
B.length ByteString
blockHashTreeBytes) of
                    Maybe Word32
Nothing -> String -> Word32
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent share data offset"
                    Just Word32
x -> Word32
x

        -- Then there are a couple 64 bit offsets, represented as Word64s, for
        -- positions that follow the share data.
        encryptedPrivateKeyOffset :: Word64
encryptedPrivateKeyOffset =
            Word32 -> Word64
forall b a. From a b => a -> b
into @Word64 Word32
shareDataOffset
                Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ case String -> Int64 -> Maybe Word64
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word64 String
"" (ByteString -> Int64
LB.length ByteString
shareData) of
                    Maybe Word64
Nothing -> String -> Word64
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent share data length"
                    Just Word64
x -> Word64
x
        eofOffset :: Word64
eofOffset =
            Word64
encryptedPrivateKeyOffset
                Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ case String -> Int -> Maybe Word64
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Word64 String
"" (ByteString -> Int
B.length ByteString
shareEncryptedPrivateKey) of
                    Maybe Word64
Nothing -> String -> Word64
forall a. HasCallStack => String -> a
error String
"Binary.put Share could not represent encrypted private key length"
                    Just Word64
x -> Word64
x

    get :: Get Share
get = do
        Word8
version <- Get Word8
getWord8
        Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Word8
version Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0) (String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get ()) -> String -> Get ()
forall a b. (a -> b) -> a -> b
$ String
"Only version 0 is supported; got version " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Word8 -> String
forall a. Show a => a -> String
show Word8
version)
        Word64
shareSequenceNumber <- Get Word64
getWord64be
        ByteString
shareRootHash <- Int -> Get ByteString
getByteString Int
32
        ByteString
ivBytes <- Int -> Get ByteString
getByteString Int
16
        SDMF_IV
shareIV <- case ByteString -> Maybe (IV AES128)
forall b c. (ByteArrayAccess b, BlockCipher c) => b -> Maybe (IV c)
makeIV ByteString
ivBytes of
            Maybe (IV AES128)
Nothing -> String -> Get SDMF_IV
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Could not decode IV"
            Just IV AES128
iv -> SDMF_IV -> Get SDMF_IV
forall (f :: * -> *) a. Applicative f => a -> f a
pure (IV AES128 -> SDMF_IV
Keys.SDMF_IV IV AES128
iv)

        Word8
shareRequiredShares <- Get Word8
getWord8
        Word8
shareTotalShares <- Get Word8
getWord8
        Word64
shareSegmentSize <- Get Word64
getWord64be
        Word64
shareDataLength <- Get Word64
getWord64be
        Word32
signatureOffset <- Get Word32
getWord32be
        Word32
hashChainOffset <- Get Word32
getWord32be
        Word32
blockHashTreeOffset <- Get Word32
getWord32be
        Word32
shareDataOffset <- Get Word32
getWord32be
        Word64
encryptedPrivateKeyOffset <- Get Word64
getWord64be
        Word64
eofOffset <- Get Word64
getWord64be

        -- This offset is not the encoded share but it's defined as being
        -- right where we've read to.  Give it a name that follows the
        -- pattern.
        Int64
shareVerificationOffset <- Get Int64
bytesRead

        -- Read in the values between all those offsets.
        Verification
shareVerificationKey <- PublicKey -> Verification
Keys.Verification (PublicKey -> Verification) -> Get PublicKey -> Get Verification
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Get PublicKey -> Get PublicKey
forall a. Int -> Get a -> Get a
isolate (Word32 -> Int
forall a b. From a b => a -> b
from Word32
signatureOffset Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int64 -> Int
forall a b. From a b => a -> b
from Int64
shareVerificationOffset) Get PublicKey
getSubjectPublicKeyInfo
        ByteString
shareSignature <- Int -> Get ByteString
getByteString (Word32 -> Int
forall a b. From a b => a -> b
from (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ Word32
hashChainOffset Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
signatureOffset)
        HashChain
shareHashChain <- Int -> Get HashChain -> Get HashChain
forall a. Int -> Get a -> Get a
isolate (Word32 -> Int
forall a b. From a b => a -> b
from (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ Word32
blockHashTreeOffset Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
hashChainOffset) Get HashChain
forall t. Binary t => Get t
get
        MerkleTree ByteString SHA256d
shareBlockHashTree <- Int
-> Get (MerkleTree ByteString SHA256d)
-> Get (MerkleTree ByteString SHA256d)
forall a. Int -> Get a -> Get a
isolate (Word32 -> Int
forall a b. From a b => a -> b
from (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ Word32
shareDataOffset Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
blockHashTreeOffset) Get (MerkleTree ByteString SHA256d)
forall t. Binary t => Get t
get

        Int64
blockLength <- String -> Word64 -> Get Int64
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Int64 String
"Binary.get Share could not represent share block length" (Word64
encryptedPrivateKeyOffset Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word32 -> Word64
forall b a. From a b => a -> b
into @Word64 Word32
shareDataOffset)
        ByteString
shareData <- Int64 -> Get ByteString
getLazyByteString Int64
blockLength

        Int
keyBytesLength <- String -> Word64 -> Get Int
forall b a (m :: * -> *). TryFrom a b m => String -> a -> m b
tryInto @Int String
"Binary.get Share cannot represent private key length" (Word64
eofOffset Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
encryptedPrivateKeyOffset)
        ByteString
shareEncryptedPrivateKey <- Int -> Get ByteString
getByteString Int
keyBytesLength

        Bool
empty <- Get Bool
isEmpty
        Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
empty (String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Expected end of input but there are more bytes")

        Share -> Get Share
forall (f :: * -> *) a. Applicative f => a -> f a
pure Share :: Word64
-> ByteString
-> SDMF_IV
-> Word8
-> Word8
-> Word64
-> Word64
-> Verification
-> ByteString
-> HashChain
-> MerkleTree ByteString SHA256d
-> ByteString
-> ByteString
-> Share
Share{Word8
Word64
ByteString
ByteString
MerkleTree ByteString SHA256d
SDMF_IV
Verification
HashChain
shareEncryptedPrivateKey :: ByteString
shareData :: ByteString
shareBlockHashTree :: MerkleTree ByteString SHA256d
shareHashChain :: HashChain
shareSignature :: ByteString
shareVerificationKey :: Verification
shareDataLength :: Word64
shareSegmentSize :: Word64
shareTotalShares :: Word8
shareRequiredShares :: Word8
shareIV :: SDMF_IV
shareRootHash :: ByteString
shareSequenceNumber :: Word64
shareEncryptedPrivateKey :: ByteString
shareData :: ByteString
shareBlockHashTree :: MerkleTree ByteString SHA256d
shareHashChain :: HashChain
shareSignature :: ByteString
shareVerificationKey :: Verification
shareDataLength :: Word64
shareSegmentSize :: Word64
shareRequiredShares :: Word8
shareTotalShares :: Word8
shareIV :: SDMF_IV
shareRootHash :: ByteString
shareSequenceNumber :: Word64
..}

{- | Read an X.509v3-encoded SubjectPublicKeyInfo structure carrying an ASN.1
 DER encoded RSA public key.
-}
getSubjectPublicKeyInfo :: Get RSA.PublicKey
getSubjectPublicKeyInfo :: Get PublicKey
getSubjectPublicKeyInfo = do
    ByteString
bytes <- Get ByteString
getRemainingLazyByteString
    let (Right [ASN1]
asn1s) = DER -> ByteString -> Either ASN1Error [ASN1]
forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' DER
DER (ByteString -> Either ASN1Error [ASN1])
-> (ByteString -> ByteString)
-> ByteString
-> Either ASN1Error [ASN1]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LB.toStrict (ByteString -> Either ASN1Error [ASN1])
-> ByteString -> Either ASN1Error [ASN1]
forall a b. (a -> b) -> a -> b
$ ByteString
bytes
    let (Right (PubKeyRSA PublicKey
pubKey, [])) = [ASN1] -> Either String (PubKey, [ASN1])
forall a. ASN1Object a => [ASN1] -> Either String (a, [ASN1])
fromASN1 [ASN1]
asn1s
    PublicKey -> Get PublicKey
forall (f :: * -> *) a. Applicative f => a -> f a
pure PublicKey
pubKey

{- | Encode a private key to the Tahoe-LAFS canonical bytes representation -
 X.509 SubjectPublicKeyInfo of the ASN.1 DER serialization of an RSA
 PublicKey.
-}
signatureKeyToBytes :: RSA.PrivateKey -> B.ByteString
signatureKeyToBytes :: PrivateKey -> ByteString
signatureKeyToBytes = ByteString -> ByteString
LB.toStrict (ByteString -> ByteString)
-> (PrivateKey -> ByteString) -> PrivateKey -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DER -> [ASN1] -> ByteString
forall a. ASN1Encoding a => a -> [ASN1] -> ByteString
encodeASN1 DER
DER ([ASN1] -> ByteString)
-> (PrivateKey -> [ASN1]) -> PrivateKey -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PrivKey -> [ASN1] -> [ASN1]) -> [ASN1] -> PrivKey -> [ASN1]
forall a b c. (a -> b -> c) -> b -> a -> c
flip PrivKey -> [ASN1] -> [ASN1]
forall a. ASN1Object a => a -> [ASN1] -> [ASN1]
toASN1 [] (PrivKey -> [ASN1])
-> (PrivateKey -> PrivKey) -> PrivateKey -> [ASN1]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivateKey -> PrivKey
PrivKeyRSA