diff options
Diffstat (limited to 'src/Crypto/XEd25519.hs')
-rw-r--r-- | src/Crypto/XEd25519.hs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/src/Crypto/XEd25519.hs b/src/Crypto/XEd25519.hs deleted file mode 100644 index 372f31a8..00000000 --- a/src/Crypto/XEd25519.hs +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | module Crypto.XEd25519 where | ||
2 | |||
3 | import Control.Arrow | ||
4 | import Data.Bits | ||
5 | import Data.ByteArray as BA | ||
6 | import Data.Memory.PtrMethods (memCopy) | ||
7 | import Crypto.Hash | ||
8 | import Crypto.ECC.Edwards25519 | ||
9 | import Crypto.Error | ||
10 | import qualified Crypto.PubKey.Ed25519 as Ed25519 | ||
11 | import Foreign.Marshal | ||
12 | import Foreign.Ptr | ||
13 | import Foreign.Storable | ||
14 | import qualified Crypto.PubKey.Curve25519 as X25519 | ||
15 | |||
16 | import Crypto.XEd25519.FieldElement | ||
17 | import Crypto.Nonce | ||
18 | |||
19 | |||
20 | data SecretKey = SecretKey { secretScalar :: Scalar } | ||
21 | |||
22 | data PublicKey = PublicKey Ed25519.PublicKey | ||
23 | deriving Eq | ||
24 | |||
25 | type Nonce = Nonce32 | ||
26 | |||
27 | newtype EncodedPoint = EncodedPoint Point | ||
28 | |||
29 | instance ByteArrayAccess SecretKey where | ||
30 | length _ = 32 | ||
31 | withByteArray (SecretKey scalar) = withByteArray (scalarEncode scalar :: Bytes) | ||
32 | |||
33 | instance ByteArrayAccess PublicKey where | ||
34 | length _ = 32 | ||
35 | withByteArray (PublicKey edpub) = withByteArray edpub | ||
36 | |||
37 | instance ByteArrayAccess EncodedPoint where | ||
38 | length _ = 32 | ||
39 | withByteArray (EncodedPoint pt) f = | ||
40 | withByteArray (pointEncode pt :: Bytes) f | ||
41 | |||
42 | |||
43 | data Signature = Signature EncodedPoint Scalar | ||
44 | |||
45 | instance ByteArrayAccess Signature where | ||
46 | length _ = 64 | ||
47 | withByteArray (Signature pt scalar) f = | ||
48 | withByteArray pt $ \ptptr -> do | ||
49 | withByteArray (SecretKey scalar) $ \scalarptr -> do | ||
50 | allocaBytes 64 $ \ptr -> do | ||
51 | memCopy ptr ptptr 32 | ||
52 | memCopy (ptr `plusPtr` 32) scalarptr 32 | ||
53 | f (castPtr ptr) | ||
54 | |||
55 | |||
56 | padding :: Bytes | ||
57 | padding = 0xFE `BA.cons` BA.replicate 31 0xFF | ||
58 | |||
59 | sign :: ByteArrayAccess dta => dta -> Nonce -> SecretKey -> PublicKey -> Signature | ||
60 | sign dta nonce sec pub = Signature rB s | ||
61 | where | ||
62 | rB = ge_p3_tobytes $ ge_scalarmult_base r | ||
63 | |||
64 | r = sc_reduce $ hashFinalize $ (`hashUpdate` padding) | ||
65 | >>> (`hashUpdate` sec) | ||
66 | >>> (`hashUpdate` dta) | ||
67 | >>> (`hashUpdate` nonce) $ hashInit | ||
68 | |||
69 | h = sc_reduce $ hashFinalize $ (`hashUpdate` rB) | ||
70 | >>> (`hashUpdate` pub) | ||
71 | >>> (`hashUpdate` dta) $ hashInit | ||
72 | |||
73 | -- s = r + ha (mod q) | ||
74 | s = sc_muladd h (secretScalar sec) r | ||
75 | |||
76 | |||
77 | |||
78 | ge_p3_tobytes :: Point -> EncodedPoint | ||
79 | ge_p3_tobytes = EncodedPoint | ||
80 | |||
81 | ge_scalarmult_base :: Scalar -> Point | ||
82 | ge_scalarmult_base = toPoint | ||
83 | |||
84 | sc_muladd :: Scalar -> Scalar -> Scalar -> Scalar | ||
85 | sc_muladd a b c = scalarAdd (scalarMul a b) c | ||
86 | |||
87 | sc_reduce :: Digest SHA512 -> Scalar | ||
88 | sc_reduce digest = x where CryptoPassed x = scalarDecodeLong digest -- ??? | ||
89 | |||
90 | -- Scalar is internally, at least on 64bit machines, represented as 5 | ||
91 | -- 56-bit words in little-endian order, each encoded as a Word64. | ||
92 | sc_neg :: Scalar -> Scalar | ||
93 | sc_neg = scalarMul sc_neg1 | ||
94 | |||
95 | verify :: ByteArrayAccess dta => PublicKey -> dta -> Signature -> Bool | ||
96 | verify pub dta signature = Ed25519.verify ed_pub dta ed_sig | ||
97 | where | ||
98 | CryptoPassed ed_pub = Ed25519.publicKey pub' | ||
99 | CryptoPassed ed_sig = Ed25519.signature signature' | ||
100 | |||
101 | -- Get the sign bit from the s part of the signature. | ||
102 | sign_bit = BA.index signature 63 .&. 0x80 | ||
103 | |||
104 | -- Set the sign bit to zero in the s part of the signature. | ||
105 | signature' :: Bytes | ||
106 | signature' = BA.copyAndFreeze signature $ \ptr -> do | ||
107 | let at63 = plusPtr ptr 63 | ||
108 | byte63 <- peek at63 | ||
109 | poke at63 $ byte63 .&. (0x7F `asTypeOf` sign_bit) | ||
110 | |||
111 | -- Restore the sign bit on the verification key, which should have 0 as its | ||
112 | -- current sign bit. | ||
113 | pub' :: Bytes | ||
114 | pub' = BA.copyAndFreeze pub $ \ptr -> do | ||
115 | let at31 = plusPtr ptr 31 | ||
116 | byte31 <- peek at31 | ||
117 | poke at31 $ (byte31 .&. 0x7F) .|. sign_bit | ||
118 | |||
119 | |||
120 | -- typedef crypto_int32 fe[10]; | ||
121 | -- | ||
122 | -- fe means field element. Here the field is \Z/(2^255-19). | ||
123 | -- An element t, entries t[0]...t[9], represents the integer | ||
124 | -- t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. | ||
125 | -- Bounds on each t[i] vary depending on context. | ||
126 | |||
127 | -- mont_pub_to_ed_pub | ||
128 | toSigningKey :: X25519.PublicKey -> PublicKey | ||
129 | toSigningKey mont_pub0 = PublicKey ed_pub | ||
130 | where | ||
131 | -- Read the public key as a field element | ||
132 | mont_pub = fe_frombytes mont_pub0 | ||
133 | |||
134 | -- Convert the Montgomery public key to a twisted Edwards public key | ||
135 | fe_ONE = fe_1 | ||
136 | |||
137 | -- Calculate the parameters (u - 1) and (u + 1) | ||
138 | mont_pub_minus_one = fe_sub mont_pub fe_ONE | ||
139 | mont_pub_plus_one0 = fe_add mont_pub fe_ONE | ||
140 | |||
141 | -- Prepare inv(u + 1) | ||
142 | mont_pub_plus_one = fe_invert mont_pub_plus_one0 | ||
143 | |||
144 | -- Calculate y = (u - 1) * inv(u + 1) (mod p) | ||
145 | ed_pub0 = fe_mul mont_pub_minus_one mont_pub_plus_one | ||
146 | ed_pub = fe_tobytes ed_pub0 | ||
147 | |||
148 | -- mont_priv_to_ed_pair | ||
149 | toSigningKeyPair :: X25519.SecretKey -> (SecretKey,PublicKey) | ||
150 | toSigningKeyPair mont_priv0 = (SecretKey ed_priv, PublicKey ed_pub) | ||
151 | where | ||
152 | -- Prepare a buffer for the twisted Edwards private key | ||
153 | ed_priv1 = (throwCryptoError . scalarDecodeLong :: X25519.SecretKey -> Scalar) mont_priv0 | ||
154 | |||
155 | -- Get the twisted edwards public key, including the sign bit | ||
156 | ed_pub0 = ge_p3_tobytes $ ge_scalarmult_base ed_priv1 | ||
157 | |||
158 | -- Save the sign bit for later | ||
159 | sign_bit = (BA.index ed_pub0 31 `shiftR` 7) .&. 1 | ||
160 | |||
161 | -- Force the sign bit to zero | ||
162 | pub' :: Bytes | ||
163 | pub' = BA.copyAndFreeze ed_pub0 $ \ptr -> do | ||
164 | let at31 = plusPtr ptr 31 | ||
165 | byte31 <- peek at31 | ||
166 | poke at31 $ (byte31 .&. 0x7F) `asTypeOf` sign_bit | ||
167 | |||
168 | CryptoPassed ed_pub = Ed25519.publicKey pub' | ||
169 | |||
170 | |||
171 | -- Prepare the negated private key | ||
172 | ed_priv_neg = sc_neg ed_priv1 | ||
173 | |||
174 | -- Get the correct private key based on the sign stored above | ||
175 | ed_priv = if sign_bit/=0 then ed_priv_neg | ||
176 | else ed_priv1 | ||
177 | |||
178 | -- sc_zero = throwCryptoError $ scalarDecodeLong (b::Bytes) | ||
179 | -- where | ||
180 | -- b = BA.pack $ encodeLittleEndian $ 2^252 + 27742317777372353535851937790883648493 | ||
181 | |||
182 | sc_neg1 :: Scalar | ||
183 | sc_neg1 = throwCryptoError $ scalarDecodeLong (b::Bytes) | ||
184 | where | ||
185 | b = BA.pack $ encodeLittleEndian $ 2^252 + 27742317777372353535851937790883648492 | ||