@@ -12,12 +12,15 @@ module Pos.Util.Mnemonic
12
12
, MnemonicWords
13
13
14
14
-- * Errors
15
- , MnemonicErr (.. )
15
+ , MnemonicError (.. )
16
16
, MnemonicException (.. )
17
+ -- ** Re-exports from 'cardano-crypto'
18
+ , EntropyError (.. )
19
+ , DictionaryError (.. )
20
+ , MnemonicWordsError (.. )
17
21
18
22
-- * Creating @Mnemonic@ (resp. @Entropy@)
19
23
, mkEntropy
20
- , eitherToParser
21
24
, mkMnemonic
22
25
, genEntropy
23
26
@@ -27,14 +30,17 @@ module Pos.Util.Mnemonic
27
30
, mnemonicToAesKey
28
31
, entropyToMnemonic
29
32
, entropyToByteString
33
+
34
+ -- * Helper (FIXME: Move to a separated module)
35
+ , eitherToParser
30
36
) where
31
37
32
38
import Universum
33
39
34
40
import Basement.Sized.List (unListN )
41
+ import Control.Arrow (left )
35
42
import Control.Lens ((?~) )
36
43
import Crypto.Encoding.BIP39
37
- import Crypto.Encoding.BIP39.Dictionary (mnemonicSentenceToListN )
38
44
import Crypto.Hash (Blake2b_256 , Digest , hash )
39
45
import Data.Aeson (FromJSON (.. ), ToJSON (.. ))
40
46
import Data.Aeson.Types (Parser )
@@ -75,14 +81,15 @@ data Mnemonic (mw :: Nat) = Mnemonic
75
81
-- ERRORS
76
82
--
77
83
78
- data MnemonicException = UnexpectedMnemonicErr MnemonicErr
84
+ data MnemonicException csz = UnexpectedEntropyError ( EntropyError csz )
79
85
deriving (Show , Typeable )
80
86
81
87
82
- data MnemonicErr
83
- = MnemonicErrInvalidEntropyLength Int
84
- | MnemonicErrFailedToCreate
85
- | MnemonicErrForbiddenMnemonic
88
+ data MnemonicError csz
89
+ = ErrMnemonicWords MnemonicWordsError
90
+ | ErrEntropy (EntropyError csz )
91
+ | ErrDictionary DictionaryError
92
+ | ErrForbidden
86
93
deriving (Show )
87
94
88
95
@@ -94,12 +101,8 @@ data MnemonicErr
94
101
mkEntropy
95
102
:: forall n csz . (ValidEntropySize n , ValidChecksumSize n csz )
96
103
=> ByteString
97
- -> Either MnemonicErr (Entropy n )
98
- mkEntropy =
99
- let
100
- n = fromIntegral $ natVal (Proxy @ n )
101
- in
102
- maybe (Left $ MnemonicErrInvalidEntropyLength n) Right . toEntropy @ n
104
+ -> Either (EntropyError csz ) (Entropy n )
105
+ mkEntropy = toEntropy
103
106
104
107
105
108
-- | Generate Entropy of a given size using a random seed.
@@ -115,7 +118,7 @@ genEntropy =
115
118
size =
116
119
fromIntegral $ natVal (Proxy @ n )
117
120
eitherToIO =
118
- either (throwM . UnexpectedMnemonicErr ) return
121
+ either (throwM . UnexpectedEntropyError ) return
119
122
in
120
123
(eitherToIO . mkEntropy) =<< Crypto. getEntropy (size `div` 8 )
121
124
@@ -127,22 +130,20 @@ mkMnemonic
127
130
, EntropySize mw ~ n
128
131
)
129
132
=> [Text ]
130
- -> Either MnemonicErr (Mnemonic mw )
133
+ -> Either ( MnemonicError csz ) (Mnemonic mw )
131
134
mkMnemonic wordsm = do
132
- sentence <- maybe
133
- (Left MnemonicErrFailedToCreate )
134
- (Right . mnemonicPhraseToMnemonicSentence Dictionary. english)
135
- (mnemonicPhrase @ mw (toUtf8String <$> wordsm))
135
+ phrase <- left ErrMnemonicWords
136
+ $ mnemonicPhrase @ mw (toUtf8String <$> wordsm)
137
+
138
+ sentence <- left ErrDictionary
139
+ $ mnemonicPhraseToMnemonicSentence Dictionary. english phrase
136
140
137
- entropy <- maybe
138
- (Left MnemonicErrFailedToCreate )
139
- Right
140
- (wordsToEntropy sentence :: Maybe (Entropy n ))
141
+ entropy <- left ErrEntropy
142
+ $ wordsToEntropy sentence
141
143
142
- when (isForbiddenMnemonic sentence) $
143
- Left MnemonicErrForbiddenMnemonic
144
+ when (isForbiddenMnemonic sentence) $ Left ErrForbidden
144
145
145
- pure $ Mnemonic
146
+ pure Mnemonic
146
147
{ mnemonicToEntropy = entropy
147
148
, mnemonicToSentence = sentence
148
149
}
@@ -260,7 +261,7 @@ instance
260
261
size = fromIntegral $ natVal (Proxy @ n )
261
262
entropy = mkEntropy @ n . B8. pack <$> vectorOf (size `quot` 8 ) arbitrary
262
263
in
263
- either (error . show . UnexpectedMnemonicErr ) identity <$> entropy
264
+ either (error . show . UnexpectedEntropyError ) identity <$> entropy
264
265
265
266
266
267
-- Same remark from 'Arbitrary Entropy' applies here.
@@ -276,7 +277,7 @@ instance
276
277
entropyToMnemonic <$> arbitrary @ (Entropy n )
277
278
278
279
279
- instance Exception MnemonicException
280
+ instance ( KnownNat csz ) => Exception ( MnemonicException csz )
280
281
281
282
282
283
-- FIXME: Suggestion, we could -- when certain flags are turned on -- display
@@ -294,15 +295,22 @@ instance Buildable (SecureLog (Mnemonic mw)) where
294
295
build _ =
295
296
" <mnemonic>"
296
297
297
- instance Buildable MnemonicErr where
298
+ instance Buildable ( MnemonicError csz ) where
298
299
build = \ case
299
- MnemonicErrInvalidEntropyLength l ->
300
- bprint (" Entropy must be a sequence of " % build % " bytes" ) l
301
- MnemonicErrFailedToCreate ->
302
- bprint " Invalid Mnemonic words"
303
- MnemonicErrForbiddenMnemonic ->
300
+ ErrMnemonicWords (ErrWrongNumberOfWords a e) ->
301
+ bprint (" Invalid number of mnemonic words: got " % build% " words, expected " % build% " words" ) a e
302
+ ErrDictionary (ErrInvalidDictionaryWord w) ->
303
+ bprint (" Invalid dictionary word: " % build% " " ) (fromUtf8String w)
304
+ ErrEntropy (ErrInvalidEntropyLength a e) ->
305
+ bprint (" Invalid entropy length: got " % build% " bits, expected " % build% " bits" ) a e
306
+ ErrEntropy (ErrInvalidEntropyChecksum a e) ->
307
+ bprint (" Invalid entropy checksum: got " % build% " , expected " % build) (show' a) (show' e)
308
+ ErrForbidden ->
304
309
bprint " Forbidden Mnemonic: an example Mnemonic has been submitted. \
305
310
\Please generate a fresh and private Mnemonic from a trusted source"
311
+ where
312
+ show' :: Checksum csz -> String
313
+ show' = show
306
314
307
315
308
316
-- | To use everytime we need to show an example of a Mnemonic. This particular
@@ -325,13 +333,13 @@ instance Default (Mnemonic 12) where
325
333
, " flee"
326
334
]
327
335
328
- sentence = maybe
329
- (error $ show $ UnexpectedMnemonicErr MnemonicErrFailedToCreate )
330
- (mnemonicPhraseToMnemonicSentence Dictionary. english)
336
+ phrase = either (error . show ) id
331
337
(mnemonicPhrase @ 12 (toUtf8String <$> wordsm))
332
338
333
- entropy = fromMaybe
334
- (error $ show $ UnexpectedMnemonicErr MnemonicErrFailedToCreate )
339
+ sentence = either (error . show ) id
340
+ (mnemonicPhraseToMnemonicSentence Dictionary. english phrase)
341
+
342
+ entropy = either (error . show ) id
335
343
(wordsToEntropy @ (EntropySize 12 ) sentence)
336
344
in Mnemonic
337
345
{ mnemonicToSentence = sentence
0 commit comments