3838from hikari .api import special_endpoints
3939from hikari .interactions import base_interactions
4040from hikari .internal import data_binding
41- from hikari .internal import ed25519
4241
4342if typing .TYPE_CHECKING :
4443 import socket as socket_
4544 import ssl
4645
4746 import aiohttp .typedefs
4847
48+ # This is kept inline as pynacl is an optional dependency.
49+ from nacl import signing
50+
4951 from hikari .api import entity_factory as entity_factory_api
5052 from hikari .api import rest as rest_api
5153 from hikari .interactions import command_interactions
5254 from hikari .interactions import component_interactions
5355
5456 _InteractionT_co = typing .TypeVar ("_InteractionT_co" , bound = base_interactions .PartialInteraction , covariant = True )
55- _ResponseT_co = typing .TypeVar ("_ResponseT_co" , bound = special_endpoints .InteractionResponseBuilder , covariant = True )
5657 _MessageResponseBuilderT = typing .Union [
5758 special_endpoints .InteractionDeferredBuilder ,
5859 special_endpoints .InteractionMessageBuilder ,
@@ -151,9 +152,10 @@ class InteractionServer(interaction_server.InteractionServer):
151152 "_is_closing" ,
152153 "_listeners" ,
153154 "_loads" ,
155+ "_nacl" ,
156+ "_public_key" ,
154157 "_rest_client" ,
155158 "_server" ,
156- "_verify" ,
157159 )
158160
159161 def __init__ (
@@ -165,6 +167,16 @@ def __init__(
165167 rest_client : rest_api .RESTClient ,
166168 public_key : typing .Optional [bytes ] = None ,
167169 ) -> None :
170+ # This is kept inline as pynacl is an optional dependency.
171+ try :
172+ import nacl .exceptions
173+ import nacl .signing
174+
175+ except ModuleNotFoundError as exc :
176+ raise RuntimeError (
177+ "You must install the optional `hikari[server]` dependencies to use the default interaction server."
178+ ) from exc
179+
168180 # Building asyncio.Lock when there isn't a running loop may lead to runtime errors.
169181 self ._application_fetch_lock : typing .Optional [asyncio .Lock ] = None
170182 # Building asyncio.Event when there isn't a running loop may lead to runtime errors.
@@ -174,9 +186,10 @@ def __init__(
174186 self ._is_closing = False
175187 self ._listeners : typing .Dict [typing .Type [base_interactions .PartialInteraction ], typing .Any ] = {}
176188 self ._loads = loads
189+ self ._nacl = nacl
177190 self ._rest_client = rest_client
178191 self ._server : typing .Optional [aiohttp .web_runner .AppRunner ] = None
179- self ._verify = ed25519 . build_ed25519_verifier (public_key ) if public_key is not None else None
192+ self ._public_key = nacl . signing . VerifyKey (public_key ) if public_key is not None else None
180193
181194 @property
182195 def is_alive (self ) -> bool :
@@ -189,23 +202,23 @@ def is_alive(self) -> bool:
189202 """
190203 return self ._server is not None
191204
192- async def _fetch_public_key (self ) -> ed25519 . VerifierT :
205+ async def _fetch_public_key (self ) -> signing . VerifyKey :
193206 if self ._application_fetch_lock is None :
194207 self ._application_fetch_lock = asyncio .Lock ()
195208
196209 application : typing .Union [applications .Application , applications .AuthorizationApplication ]
197210 async with self ._application_fetch_lock :
198- if self ._verify :
199- return self ._verify
211+ if self ._public_key :
212+ return self ._public_key
200213
201214 if self ._rest_client .token_type == applications .TokenType .BOT :
202215 application = await self ._rest_client .fetch_application ()
203216
204217 else :
205218 application = (await self ._rest_client .fetch_authorization ()).application
206219
207- self ._verify = ed25519 . build_ed25519_verifier (application .public_key )
208- return self ._verify
220+ self ._public_key = self . _nacl . signing . VerifyKey (application .public_key )
221+ return self ._public_key
209222
210223 async def aiohttp_hook (self , request : aiohttp .web .Request ) -> aiohttp .web .Response :
211224 """Handle an AIOHTTP interaction request.
@@ -320,9 +333,12 @@ async def on_interaction(self, body: bytes, signature: bytes, timestamp: bytes)
320333 Instructions on how the REST server calling this should respond to
321334 the interaction request.
322335 """
323- verify = self ._verify or await self ._fetch_public_key ()
336+ public_key = self ._public_key or await self ._fetch_public_key ()
337+
338+ try :
339+ public_key .verify (timestamp + body , signature )
324340
325- if not verify ( body , signature , timestamp ):
341+ except ( self . _nacl . exceptions . BadSignatureError , ValueError ):
326342 _LOGGER .error ("Received a request with an invalid signature" )
327343 return _Response (_BAD_REQUEST_STATUS , b"Invalid request signature" )
328344
0 commit comments