packages feed

botan-low-0.0.1.0: test/Botan/Low/PubKeySpec.hs

module Main where

import Test.Prelude

import Botan.Low.MPI
import Botan.Low.RNG
import Botan.Low.PubKey

ecGroup :: ByteString
ecGroup = "secp256r1"

dlGroup :: ByteString
dlGroup = "modp/ietf/1024"

-- TODO: More exhaustive testing in botan
-- pks :: [(PKName, PKParams)]
pks :: [(ByteString, ByteString)]
pks =
    [ ("RSA", "2048")
    , ("SM2", ecGroup)
    , ("ElGamal", dlGroup)
    , ("DSA", dlGroup)
    , ("ECDSA", ecGroup)
    , ("ECKCDSA", ecGroup)
    , ("ECGDSA", ecGroup)
    , ("GOST-34.10", ecGroup)
    , ("Ed25519", "")
    , ("XMSS",  "XMSS-SHAKE_10_256")    -- NOTE: XMSS is noticeably slower than other keys and
                                        -- the _16 and _20 variants are exponentially slower
    , ("DH", dlGroup)
    , ("ECDH", ecGroup)
    , ("Curve25519", "")
    -- TODO: Dilithium-x-y
    , ("Dilithium", "")
    -- TODO: Kyber-x-y
    , ("Kyber", "")
    -- TODO: SPHINCS+
    -- https://github.com/randombit/botan/blob/a303f4af1504e7ac349dd798190924ea08ead9b7/src/lib/pubkey/sphincsplus/sphincsplus_common/sp_parameters.cpp#L155
    -- , ("SPHINCS+", "sha2-128s-r3.1") -- Not working
    , ("McEliece", "")
    ]

pkTestName :: (ByteString, ByteString) -> String
pkTestName (pk, param) = chars $ pk <> " " <> param

-- NOTE: Known fields are: n, e, p, q, g, a, b
--  ECGroup PrivKey: x plus all in PubKey
--  EGGroup PubKey: public_x, public_y, base_x, base_y, p, a, b, cofactor, order
--  DLGroup PubKey: p, q, g, y (not all groups have all four)
--  DLGroup PrivKey: p, q, g, x, y
--  RSA PubKey: p, q, d, c, d1, d2
--  RSA PrivKey: n, e, d, p, q, d1, d2, c

ecGroupPrivFields = [ "x" , "public_x", "public_y", "base_x", "base_y", "p", "a", "b", "cofactor", "order" ]
ecGroupPubFields = [ "public_x", "public_y", "base_x", "base_y", "p", "a", "b", "cofactor", "order" ]

dlGroupPrivFields = [ "p", "q", "g", "x", "y" ]
dlGroupPubFields = [ "p", "q", "g", "y" ]

privKeyFields "RSA"         = [ "p", "q", "d", "n", "e"] -- TODO: Check
privKeyFields "SM2"         = ecGroupPrivFields
privKeyFields "ElGamal"     = dlGroupPrivFields
privKeyFields "DSA"         = dlGroupPrivFields
privKeyFields "ECDSA"       = ecGroupPrivFields
privKeyFields "ECKCDSA"     = ecGroupPrivFields
privKeyFields "ECGDSA"      = ecGroupPrivFields
privKeyFields "GOST-34.10"  = ecGroupPrivFields
privKeyFields "Ed25519"     = [] -- TODO
privKeyFields "XMSS"        = [] -- TODO
privKeyFields "DH"          = dlGroupPrivFields
privKeyFields "ECDH"        = ecGroupPrivFields
privKeyFields "Curve25519"  = [] -- TODO
privKeyFields "Dilithium"   = [] -- TODO
privKeyFields "Kyber"       = [] -- TODO
privKeyFields "McEliece"    = [] -- TODO

pubKeyFields "RSA"         = [ "n", "e" ]
pubKeyFields "SM2"         = ecGroupPubFields
pubKeyFields "ElGamal"     = dlGroupPubFields
pubKeyFields "DSA"         = dlGroupPubFields
pubKeyFields "ECDSA"       = ecGroupPubFields
pubKeyFields "ECKCDSA"     = ecGroupPubFields
pubKeyFields "ECGDSA"      = ecGroupPubFields
pubKeyFields "GOST-34.10"  = ecGroupPubFields
pubKeyFields "Ed25519"     = [] -- TODO
pubKeyFields "XMSS"        = [] -- TODO
pubKeyFields "DH"          = dlGroupPubFields
pubKeyFields "ECDH"        = ecGroupPubFields
pubKeyFields "Curve25519"  = [] -- TODO
pubKeyFields "Dilithium"   = [] -- TODO
pubKeyFields "Kyber"       = [] -- TODO
pubKeyFields "McEliece"    = [] -- TODO

-- NOTE: These tests are going to be very slow if we create new keys every time
main :: IO ()
main = hspec $ testSuite pks pkTestName $ \ (pk, param) -> do
    it "privKeyCreate" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pass
    it "privKeyCheckKey" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        privKeyCheckKey privKey rng CheckKeyNormalTests
        -- privKeyCheckKey privKey rng CheckKeyExpensiveTests
        pass
    it "privKeyExport" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        privKeyDER <- privKeyExport privKey PrivKeyExportDER
        privKeyPEM <- privKeyExport privKey PrivKeyExportPEM
        pass
    it "privKeyLoad" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        privKeyDER <- privKeyExport privKey PrivKeyExportDER
        privKeyPEM <- privKeyExport privKey PrivKeyExportPEM
        privKeyLoad privKeyDER ""
        privKeyLoad privKeyPEM ""
        pass
    it "privKeyAlgoName" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        privKeyAlgoName privKey
        pass
    it "privKeyExportPubKey" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pass
    it "pubKeyCheckKey" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyCheckKey pubKey rng CheckKeyNormalTests
        -- pubKeyCheckKey pubKey rng CheckKeyExpensiveTests
        pass
    it "pubKeyExport" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyDER <- pubKeyExport pubKey PrivKeyExportDER
        pubKeyPEM <- pubKeyExport pubKey PrivKeyExportPEM
        pass
    it "pubKeyLoad" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyDER <- pubKeyExport pubKey PrivKeyExportDER
        pubKeyPEM <- pubKeyExport pubKey PrivKeyExportPEM
        pubKeyLoad pubKeyDER
        pubKeyLoad pubKeyPEM
        pass
    it "pubKeyAlgoName" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyAlgoName pubKey
        pass
    it "pubKeyEstimatedStrength" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyEstimatedStrength pubKey
        pass
    it "pubKeyFingerprint" $ do
        rng <- rngInit "system"
        privKey <- privKeyCreate pk param rng
        pubKey <- privKeyExportPubKey privKey
        pubKeyFingerprint pubKey "SHA-256"
        pass
    describe "privKeyGetField" $ do
        forM_ (privKeyFields pk) $ \ field -> do
            it (chars field) $ do
                rng <- rngInit "system"
                privKey <- privKeyCreate pk param rng
                mp <- mpInit
                privKeyGetField mp privKey field
                pass
    describe "pubKeyGetField" $ do
        forM_ (pubKeyFields pk) $ \ field -> do
            it (chars field) $ do
                rng <- rngInit "system"
                privKey <- privKeyCreate pk param rng
                pubKey <- privKeyExportPubKey privKey
                mp <- mpInit
                pubKeyGetField mp pubKey field
                pass