Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PyNaCl-1.6.2-py3.11-linux-x86_64.egg/nacl/bindings/crypto_kx.py: 33%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

42 statements  

1# Copyright 2018 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 __future__ import annotations 

15 

16from nacl import exceptions as exc 

17from nacl._sodium import ffi, lib 

18from nacl.exceptions import ensure 

19 

20__all__ = [ 

21 "crypto_kx_PUBLIC_KEY_BYTES", 

22 "crypto_kx_SECRET_KEY_BYTES", 

23 "crypto_kx_SEED_BYTES", 

24 "crypto_kx_SESSION_KEY_BYTES", 

25 "crypto_kx_client_session_keys", 

26 "crypto_kx_keypair", 

27 "crypto_kx_server_session_keys", 

28] 

29 

30""" 

31Implementations of client, server key exchange 

32""" 

33crypto_kx_PUBLIC_KEY_BYTES: int = lib.crypto_kx_publickeybytes() 

34crypto_kx_SECRET_KEY_BYTES: int = lib.crypto_kx_secretkeybytes() 

35crypto_kx_SEED_BYTES: int = lib.crypto_kx_seedbytes() 

36crypto_kx_SESSION_KEY_BYTES: int = lib.crypto_kx_sessionkeybytes() 

37 

38 

39def crypto_kx_keypair() -> tuple[bytes, bytes]: 

40 """ 

41 Generate a key pair. 

42 This is a duplicate crypto_box_keypair, but 

43 is included for api consistency. 

44 :return: (public_key, secret_key) 

45 :rtype: (bytes, bytes) 

46 """ 

47 public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES) 

48 secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES) 

49 res = lib.crypto_kx_keypair(public_key, secret_key) 

50 ensure(res == 0, "Key generation failed.", raising=exc.CryptoError) 

51 

52 return ( 

53 ffi.buffer(public_key, crypto_kx_PUBLIC_KEY_BYTES)[:], 

54 ffi.buffer(secret_key, crypto_kx_SECRET_KEY_BYTES)[:], 

55 ) 

56 

57 

58def crypto_kx_seed_keypair(seed: bytes) -> tuple[bytes, bytes]: 

59 """ 

60 Generate a key pair with a given seed. 

61 This is functionally the same as crypto_box_seed_keypair, however 

62 it uses the blake2b hash primitive instead of sha512. 

63 It is included mainly for api consistency when using crypto_kx. 

64 :param seed: random seed 

65 :type seed: bytes 

66 :return: (public_key, secret_key) 

67 :rtype: (bytes, bytes) 

68 """ 

69 public_key = ffi.new("unsigned char[]", crypto_kx_PUBLIC_KEY_BYTES) 

70 secret_key = ffi.new("unsigned char[]", crypto_kx_SECRET_KEY_BYTES) 

71 ensure( 

72 isinstance(seed, bytes) and len(seed) == crypto_kx_SEED_BYTES, 

73 f"Seed must be a {crypto_kx_SEED_BYTES} byte long bytes sequence", 

74 raising=exc.TypeError, 

75 ) 

76 res = lib.crypto_kx_seed_keypair(public_key, secret_key, seed) 

77 ensure(res == 0, "Key generation failed.", raising=exc.CryptoError) 

78 

79 return ( 

80 ffi.buffer(public_key, crypto_kx_PUBLIC_KEY_BYTES)[:], 

81 ffi.buffer(secret_key, crypto_kx_SECRET_KEY_BYTES)[:], 

82 ) 

83 

84 

85def crypto_kx_client_session_keys( 

86 client_public_key: bytes, 

87 client_secret_key: bytes, 

88 server_public_key: bytes, 

89) -> tuple[bytes, bytes]: 

90 """ 

91 Generate session keys for the client. 

92 :param client_public_key: 

93 :type client_public_key: bytes 

94 :param client_secret_key: 

95 :type client_secret_key: bytes 

96 :param server_public_key: 

97 :type server_public_key: bytes 

98 :return: (rx_key, tx_key) 

99 :rtype: (bytes, bytes) 

100 """ 

101 ensure( 

102 isinstance(client_public_key, bytes) 

103 and len(client_public_key) == crypto_kx_PUBLIC_KEY_BYTES, 

104 f"Client public key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

105 raising=exc.TypeError, 

106 ) 

107 ensure( 

108 isinstance(client_secret_key, bytes) 

109 and len(client_secret_key) == crypto_kx_SECRET_KEY_BYTES, 

110 f"Client secret key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

111 raising=exc.TypeError, 

112 ) 

113 ensure( 

114 isinstance(server_public_key, bytes) 

115 and len(server_public_key) == crypto_kx_PUBLIC_KEY_BYTES, 

116 f"Server public key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

117 raising=exc.TypeError, 

118 ) 

119 

120 rx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES) 

121 tx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES) 

122 res = lib.crypto_kx_client_session_keys( 

123 rx_key, tx_key, client_public_key, client_secret_key, server_public_key 

124 ) 

125 ensure( 

126 res == 0, 

127 "Client session key generation failed.", 

128 raising=exc.CryptoError, 

129 ) 

130 

131 return ( 

132 ffi.buffer(rx_key, crypto_kx_SESSION_KEY_BYTES)[:], 

133 ffi.buffer(tx_key, crypto_kx_SESSION_KEY_BYTES)[:], 

134 ) 

135 

136 

137def crypto_kx_server_session_keys( 

138 server_public_key: bytes, 

139 server_secret_key: bytes, 

140 client_public_key: bytes, 

141) -> tuple[bytes, bytes]: 

142 """ 

143 Generate session keys for the server. 

144 :param server_public_key: 

145 :type server_public_key: bytes 

146 :param server_secret_key: 

147 :type server_secret_key: bytes 

148 :param client_public_key: 

149 :type client_public_key: bytes 

150 :return: (rx_key, tx_key) 

151 :rtype: (bytes, bytes) 

152 """ 

153 ensure( 

154 isinstance(server_public_key, bytes) 

155 and len(server_public_key) == crypto_kx_PUBLIC_KEY_BYTES, 

156 f"Server public key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

157 raising=exc.TypeError, 

158 ) 

159 ensure( 

160 isinstance(server_secret_key, bytes) 

161 and len(server_secret_key) == crypto_kx_SECRET_KEY_BYTES, 

162 f"Server secret key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

163 raising=exc.TypeError, 

164 ) 

165 ensure( 

166 isinstance(client_public_key, bytes) 

167 and len(client_public_key) == crypto_kx_PUBLIC_KEY_BYTES, 

168 f"Client public key must be a {crypto_kx_PUBLIC_KEY_BYTES} bytes long bytes sequence", 

169 raising=exc.TypeError, 

170 ) 

171 

172 rx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES) 

173 tx_key = ffi.new("unsigned char[]", crypto_kx_SESSION_KEY_BYTES) 

174 res = lib.crypto_kx_server_session_keys( 

175 rx_key, tx_key, server_public_key, server_secret_key, client_public_key 

176 ) 

177 ensure( 

178 res == 0, 

179 "Server session key generation failed.", 

180 raising=exc.CryptoError, 

181 ) 

182 

183 return ( 

184 ffi.buffer(rx_key, crypto_kx_SESSION_KEY_BYTES)[:], 

185 ffi.buffer(tx_key, crypto_kx_SESSION_KEY_BYTES)[:], 

186 )