Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/PyNaCl-1.6.0.dev1-py3.8-linux-x86_64.egg/nacl/bindings/crypto_sign.py: 39%

89 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-06 06:06 +0000

1# Copyright 2013 Donald Stufft and individual contributors 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14from typing import Tuple 

15 

16from nacl import exceptions as exc 

17from nacl._sodium import ffi, lib 

18from nacl.exceptions import ensure 

19 

20 

21crypto_sign_BYTES: int = lib.crypto_sign_bytes() 

22# crypto_sign_SEEDBYTES = lib.crypto_sign_seedbytes() 

23crypto_sign_SEEDBYTES: int = lib.crypto_sign_secretkeybytes() // 2 

24crypto_sign_PUBLICKEYBYTES: int = lib.crypto_sign_publickeybytes() 

25crypto_sign_SECRETKEYBYTES: int = lib.crypto_sign_secretkeybytes() 

26 

27crypto_sign_curve25519_BYTES: int = lib.crypto_box_secretkeybytes() 

28 

29crypto_sign_ed25519ph_STATEBYTES: int = lib.crypto_sign_ed25519ph_statebytes() 

30 

31 

32def crypto_sign_keypair() -> Tuple[bytes, bytes]: 

33 """ 

34 Returns a randomly generated public key and secret key. 

35 

36 :rtype: (bytes(public_key), bytes(secret_key)) 

37 """ 

38 pk = ffi.new("unsigned char[]", crypto_sign_PUBLICKEYBYTES) 

39 sk = ffi.new("unsigned char[]", crypto_sign_SECRETKEYBYTES) 

40 

41 rc = lib.crypto_sign_keypair(pk, sk) 

42 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

43 

44 return ( 

45 ffi.buffer(pk, crypto_sign_PUBLICKEYBYTES)[:], 

46 ffi.buffer(sk, crypto_sign_SECRETKEYBYTES)[:], 

47 ) 

48 

49 

50def crypto_sign_seed_keypair(seed: bytes) -> Tuple[bytes, bytes]: 

51 """ 

52 Computes and returns the public key and secret key using the seed ``seed``. 

53 

54 :param seed: bytes 

55 :rtype: (bytes(public_key), bytes(secret_key)) 

56 """ 

57 if len(seed) != crypto_sign_SEEDBYTES: 

58 raise exc.ValueError("Invalid seed") 

59 

60 pk = ffi.new("unsigned char[]", crypto_sign_PUBLICKEYBYTES) 

61 sk = ffi.new("unsigned char[]", crypto_sign_SECRETKEYBYTES) 

62 

63 rc = lib.crypto_sign_seed_keypair(pk, sk, seed) 

64 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

65 

66 return ( 

67 ffi.buffer(pk, crypto_sign_PUBLICKEYBYTES)[:], 

68 ffi.buffer(sk, crypto_sign_SECRETKEYBYTES)[:], 

69 ) 

70 

71 

72def crypto_sign(message: bytes, sk: bytes) -> bytes: 

73 """ 

74 Signs the message ``message`` using the secret key ``sk`` and returns the 

75 signed message. 

76 

77 :param message: bytes 

78 :param sk: bytes 

79 :rtype: bytes 

80 """ 

81 signed = ffi.new("unsigned char[]", len(message) + crypto_sign_BYTES) 

82 signed_len = ffi.new("unsigned long long *") 

83 

84 rc = lib.crypto_sign(signed, signed_len, message, len(message), sk) 

85 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

86 

87 return ffi.buffer(signed, signed_len[0])[:] 

88 

89 

90def crypto_sign_open(signed: bytes, pk: bytes) -> bytes: 

91 """ 

92 Verifies the signature of the signed message ``signed`` using the public 

93 key ``pk`` and returns the unsigned message. 

94 

95 :param signed: bytes 

96 :param pk: bytes 

97 :rtype: bytes 

98 """ 

99 message = ffi.new("unsigned char[]", len(signed)) 

100 message_len = ffi.new("unsigned long long *") 

101 

102 if ( 

103 lib.crypto_sign_open(message, message_len, signed, len(signed), pk) 

104 != 0 

105 ): 

106 raise exc.BadSignatureError("Signature was forged or corrupt") 

107 

108 return ffi.buffer(message, message_len[0])[:] 

109 

110 

111def crypto_sign_ed25519_pk_to_curve25519(public_key_bytes: bytes) -> bytes: 

112 """ 

113 Converts a public Ed25519 key (encoded as bytes ``public_key_bytes``) to 

114 a public Curve25519 key as bytes. 

115 

116 Raises a ValueError if ``public_key_bytes`` is not of length 

117 ``crypto_sign_PUBLICKEYBYTES`` 

118 

119 :param public_key_bytes: bytes 

120 :rtype: bytes 

121 """ 

122 if len(public_key_bytes) != crypto_sign_PUBLICKEYBYTES: 

123 raise exc.ValueError("Invalid curve public key") 

124 

125 curve_public_key_len = crypto_sign_curve25519_BYTES 

126 curve_public_key = ffi.new("unsigned char[]", curve_public_key_len) 

127 

128 rc = lib.crypto_sign_ed25519_pk_to_curve25519( 

129 curve_public_key, public_key_bytes 

130 ) 

131 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

132 

133 return ffi.buffer(curve_public_key, curve_public_key_len)[:] 

134 

135 

136def crypto_sign_ed25519_sk_to_curve25519(secret_key_bytes: bytes) -> bytes: 

137 """ 

138 Converts a secret Ed25519 key (encoded as bytes ``secret_key_bytes``) to 

139 a secret Curve25519 key as bytes. 

140 

141 Raises a ValueError if ``secret_key_bytes``is not of length 

142 ``crypto_sign_SECRETKEYBYTES`` 

143 

144 :param secret_key_bytes: bytes 

145 :rtype: bytes 

146 """ 

147 if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES: 

148 raise exc.ValueError("Invalid curve secret key") 

149 

150 curve_secret_key_len = crypto_sign_curve25519_BYTES 

151 curve_secret_key = ffi.new("unsigned char[]", curve_secret_key_len) 

152 

153 rc = lib.crypto_sign_ed25519_sk_to_curve25519( 

154 curve_secret_key, secret_key_bytes 

155 ) 

156 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

157 

158 return ffi.buffer(curve_secret_key, curve_secret_key_len)[:] 

159 

160 

161def crypto_sign_ed25519_sk_to_pk(secret_key_bytes: bytes) -> bytes: 

162 """ 

163 Extract the public Ed25519 key from a secret Ed25519 key (encoded 

164 as bytes ``secret_key_bytes``). 

165 

166 Raises a ValueError if ``secret_key_bytes``is not of length 

167 ``crypto_sign_SECRETKEYBYTES`` 

168 

169 :param secret_key_bytes: bytes 

170 :rtype: bytes 

171 """ 

172 if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES: 

173 raise exc.ValueError("Invalid secret key") 

174 

175 return secret_key_bytes[crypto_sign_SEEDBYTES:] 

176 

177 

178def crypto_sign_ed25519_sk_to_seed(secret_key_bytes: bytes) -> bytes: 

179 """ 

180 Extract the seed from a secret Ed25519 key (encoded 

181 as bytes ``secret_key_bytes``). 

182 

183 Raises a ValueError if ``secret_key_bytes``is not of length 

184 ``crypto_sign_SECRETKEYBYTES`` 

185 

186 :param secret_key_bytes: bytes 

187 :rtype: bytes 

188 """ 

189 if len(secret_key_bytes) != crypto_sign_SECRETKEYBYTES: 

190 raise exc.ValueError("Invalid secret key") 

191 

192 return secret_key_bytes[:crypto_sign_SEEDBYTES] 

193 

194 

195class crypto_sign_ed25519ph_state: 

196 """ 

197 State object wrapping the sha-512 state used in ed25519ph computation 

198 """ 

199 

200 __slots__ = ["state"] 

201 

202 def __init__(self) -> None: 

203 self.state: bytes = ffi.new( 

204 "unsigned char[]", crypto_sign_ed25519ph_STATEBYTES 

205 ) 

206 

207 rc = lib.crypto_sign_ed25519ph_init(self.state) 

208 

209 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

210 

211 

212def crypto_sign_ed25519ph_update( 

213 edph: crypto_sign_ed25519ph_state, pmsg: bytes 

214) -> None: 

215 """ 

216 Update the hash state wrapped in edph 

217 

218 :param edph: the ed25519ph state being updated 

219 :type edph: crypto_sign_ed25519ph_state 

220 :param pmsg: the partial message 

221 :type pmsg: bytes 

222 :rtype: None 

223 """ 

224 ensure( 

225 isinstance(edph, crypto_sign_ed25519ph_state), 

226 "edph parameter must be a ed25519ph_state object", 

227 raising=exc.TypeError, 

228 ) 

229 ensure( 

230 isinstance(pmsg, bytes), 

231 "pmsg parameter must be a bytes object", 

232 raising=exc.TypeError, 

233 ) 

234 rc = lib.crypto_sign_ed25519ph_update(edph.state, pmsg, len(pmsg)) 

235 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

236 

237 

238def crypto_sign_ed25519ph_final_create( 

239 edph: crypto_sign_ed25519ph_state, sk: bytes 

240) -> bytes: 

241 """ 

242 Create a signature for the data hashed in edph 

243 using the secret key sk 

244 

245 :param edph: the ed25519ph state for the data 

246 being signed 

247 :type edph: crypto_sign_ed25519ph_state 

248 :param sk: the ed25519 secret key (secret and public part) 

249 :type sk: bytes 

250 :return: ed25519ph signature 

251 :rtype: bytes 

252 """ 

253 ensure( 

254 isinstance(edph, crypto_sign_ed25519ph_state), 

255 "edph parameter must be a ed25519ph_state object", 

256 raising=exc.TypeError, 

257 ) 

258 ensure( 

259 isinstance(sk, bytes), 

260 "secret key parameter must be a bytes object", 

261 raising=exc.TypeError, 

262 ) 

263 ensure( 

264 len(sk) == crypto_sign_SECRETKEYBYTES, 

265 ("secret key must be {} bytes long").format( 

266 crypto_sign_SECRETKEYBYTES 

267 ), 

268 raising=exc.TypeError, 

269 ) 

270 signature = ffi.new("unsigned char[]", crypto_sign_BYTES) 

271 rc = lib.crypto_sign_ed25519ph_final_create( 

272 edph.state, signature, ffi.NULL, sk 

273 ) 

274 ensure(rc == 0, "Unexpected library error", raising=exc.RuntimeError) 

275 

276 return ffi.buffer(signature, crypto_sign_BYTES)[:] 

277 

278 

279def crypto_sign_ed25519ph_final_verify( 

280 edph: crypto_sign_ed25519ph_state, signature: bytes, pk: bytes 

281) -> bool: 

282 """ 

283 Verify a prehashed signature using the public key pk 

284 

285 :param edph: the ed25519ph state for the data 

286 being verified 

287 :type edph: crypto_sign_ed25519ph_state 

288 :param signature: the signature being verified 

289 :type signature: bytes 

290 :param pk: the ed25519 public part of the signing key 

291 :type pk: bytes 

292 :return: True if the signature is valid 

293 :rtype: boolean 

294 :raises exc.BadSignatureError: if the signature is not valid 

295 """ 

296 ensure( 

297 isinstance(edph, crypto_sign_ed25519ph_state), 

298 "edph parameter must be a ed25519ph_state object", 

299 raising=exc.TypeError, 

300 ) 

301 ensure( 

302 isinstance(signature, bytes), 

303 "signature parameter must be a bytes object", 

304 raising=exc.TypeError, 

305 ) 

306 ensure( 

307 len(signature) == crypto_sign_BYTES, 

308 ("signature must be {} bytes long").format(crypto_sign_BYTES), 

309 raising=exc.TypeError, 

310 ) 

311 ensure( 

312 isinstance(pk, bytes), 

313 "public key parameter must be a bytes object", 

314 raising=exc.TypeError, 

315 ) 

316 ensure( 

317 len(pk) == crypto_sign_PUBLICKEYBYTES, 

318 ("public key must be {} bytes long").format( 

319 crypto_sign_PUBLICKEYBYTES 

320 ), 

321 raising=exc.TypeError, 

322 ) 

323 rc = lib.crypto_sign_ed25519ph_final_verify(edph.state, signature, pk) 

324 if rc != 0: 

325 raise exc.BadSignatureError("Signature was forged or corrupt") 

326 

327 return True