react-native-ble-mesh 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +151 -0
- package/LICENSE +21 -0
- package/README.md +706 -0
- package/docs/API.md +462 -0
- package/docs/ARCHITECTURE.md +384 -0
- package/docs/CONTRIBUTING.md +244 -0
- package/docs/NODE_QUICKSTART.md +259 -0
- package/docs/PROTOCOL.md +195 -0
- package/docs/REACT_NATIVE.md +315 -0
- package/docs/SECURITY.md +152 -0
- package/docs/api/constants_audio.js.html +184 -0
- package/docs/api/constants_ble.js.html +165 -0
- package/docs/api/constants_crypto.js.html +107 -0
- package/docs/api/constants_errors.js.html +256 -0
- package/docs/api/constants_events.js.html +148 -0
- package/docs/api/constants_index.js.html +76 -0
- package/docs/api/constants_protocol.js.html +205 -0
- package/docs/api/crypto_aead.js.html +243 -0
- package/docs/api/crypto_chacha20.js.html +235 -0
- package/docs/api/crypto_hkdf.js.html +241 -0
- package/docs/api/crypto_hmac.js.html +197 -0
- package/docs/api/crypto_index.js.html +126 -0
- package/docs/api/crypto_keys_KeyManager.js.html +325 -0
- package/docs/api/crypto_keys_KeyPair.js.html +270 -0
- package/docs/api/crypto_keys_SecureStorage.js.html +273 -0
- package/docs/api/crypto_keys_index.js.html +86 -0
- package/docs/api/crypto_noise_handshake.js.html +464 -0
- package/docs/api/crypto_noise_index.js.html +81 -0
- package/docs/api/crypto_noise_session.js.html +307 -0
- package/docs/api/crypto_noise_state.js.html +322 -0
- package/docs/api/crypto_poly1305.js.html +167 -0
- package/docs/api/crypto_sha256.js.html +294 -0
- package/docs/api/crypto_x25519.js.html +208 -0
- package/docs/api/errors_AudioError.js.html +218 -0
- package/docs/api/errors_ConnectionError.js.html +163 -0
- package/docs/api/errors_CryptoError.js.html +157 -0
- package/docs/api/errors_HandshakeError.js.html +176 -0
- package/docs/api/errors_MeshError.js.html +154 -0
- package/docs/api/errors_MessageError.js.html +183 -0
- package/docs/api/errors_ValidationError.js.html +204 -0
- package/docs/api/errors_index.js.html +78 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/api/hooks_AppStateManager.js.html +233 -0
- package/docs/api/hooks_index.js.html +87 -0
- package/docs/api/hooks_useMesh.js.html +213 -0
- package/docs/api/hooks_useMessages.js.html +263 -0
- package/docs/api/hooks_usePeers.js.html +165 -0
- package/docs/api/index.html +868 -0
- package/docs/api/index.js.html +236 -0
- package/docs/api/mesh_dedup_BloomFilter.js.html +261 -0
- package/docs/api/mesh_dedup_DedupManager.js.html +266 -0
- package/docs/api/mesh_dedup_MessageCache.js.html +273 -0
- package/docs/api/mesh_dedup_index.js.html +70 -0
- package/docs/api/mesh_fragment_Assembler.js.html +335 -0
- package/docs/api/mesh_fragment_Fragmenter.js.html +230 -0
- package/docs/api/mesh_fragment_index.js.html +75 -0
- package/docs/api/mesh_index.js.html +72 -0
- package/docs/api/mesh_peer_Peer.js.html +296 -0
- package/docs/api/mesh_peer_PeerDiscovery.js.html +334 -0
- package/docs/api/mesh_peer_PeerManager.js.html +320 -0
- package/docs/api/mesh_peer_index.js.html +70 -0
- package/docs/api/mesh_router_MessageRouter.js.html +411 -0
- package/docs/api/mesh_router_PathFinder.js.html +386 -0
- package/docs/api/mesh_router_RouteTable.js.html +346 -0
- package/docs/api/mesh_router_index.js.html +70 -0
- package/docs/api/module-audio_buffer.html +168 -0
- package/docs/api/module-audio_buffer_FrameBuffer-FrameBuffer.html +2971 -0
- package/docs/api/module-audio_buffer_FrameBuffer.html +178 -0
- package/docs/api/module-audio_buffer_JitterBuffer-JitterBuffer.html +2761 -0
- package/docs/api/module-audio_buffer_JitterBuffer.html +178 -0
- package/docs/api/module-audio_codec.html +168 -0
- package/docs/api/module-audio_codec_LC3Codec-LC3Codec.html +2876 -0
- package/docs/api/module-audio_codec_LC3Codec.html +178 -0
- package/docs/api/module-audio_codec_LC3Decoder-LC3Decoder.html +1788 -0
- package/docs/api/module-audio_codec_LC3Decoder.html +178 -0
- package/docs/api/module-audio_codec_LC3Encoder-LC3Encoder.html +1512 -0
- package/docs/api/module-audio_codec_LC3Encoder.html +178 -0
- package/docs/api/module-audio_session.html +168 -0
- package/docs/api/module-audio_session_AudioSession-AudioSession.html +3922 -0
- package/docs/api/module-audio_session_AudioSession.html +178 -0
- package/docs/api/module-audio_session_VoiceMessage-VoiceMessage.html +3690 -0
- package/docs/api/module-audio_session_VoiceMessage-VoiceMessageRecorder.html +1780 -0
- package/docs/api/module-audio_session_VoiceMessage.html +332 -0
- package/docs/api/module-audio_transport.html +168 -0
- package/docs/api/module-audio_transport_AudioFragmenter-AudioAssembler.html +1545 -0
- package/docs/api/module-audio_transport_AudioFragmenter-AudioFragmenter.html +658 -0
- package/docs/api/module-audio_transport_AudioFragmenter.html +181 -0
- package/docs/api/module-audio_transport_AudioFramer.html +1414 -0
- package/docs/api/module-constants.html +168 -0
- package/docs/api/module-constants_audio.html +1782 -0
- package/docs/api/module-constants_ble.html +940 -0
- package/docs/api/module-constants_crypto.html +823 -0
- package/docs/api/module-constants_errors.html +316 -0
- package/docs/api/module-constants_events.html +244 -0
- package/docs/api/module-constants_protocol.html +1534 -0
- package/docs/api/module-crypto.html +169 -0
- package/docs/api/module-crypto_aead.html +1625 -0
- package/docs/api/module-crypto_chacha20.html +1440 -0
- package/docs/api/module-crypto_hkdf.html +1421 -0
- package/docs/api/module-crypto_hmac.html +828 -0
- package/docs/api/module-crypto_keys.html +169 -0
- package/docs/api/module-crypto_keys_KeyManager-KeyManager.html +2364 -0
- package/docs/api/module-crypto_keys_KeyManager.html +252 -0
- package/docs/api/module-crypto_keys_KeyPair.html +245 -0
- package/docs/api/module-crypto_keys_SecureStorage-MemorySecureStorage.html +923 -0
- package/docs/api/module-crypto_keys_SecureStorage-SecureStorage.html +942 -0
- package/docs/api/module-crypto_keys_SecureStorage.html +516 -0
- package/docs/api/module-crypto_noise.html +169 -0
- package/docs/api/module-crypto_noise_handshake-NoiseHandshake.html +2240 -0
- package/docs/api/module-crypto_noise_handshake.html +782 -0
- package/docs/api/module-crypto_noise_session-NoiseSession.html +1804 -0
- package/docs/api/module-crypto_noise_session.html +325 -0
- package/docs/api/module-crypto_noise_state-SymmetricState.html +1387 -0
- package/docs/api/module-crypto_noise_state.html +324 -0
- package/docs/api/module-crypto_poly1305.html +884 -0
- package/docs/api/module-crypto_sha256-HashContext.html +447 -0
- package/docs/api/module-crypto_sha256.html +942 -0
- package/docs/api/module-crypto_x25519.html +1503 -0
- package/docs/api/module-errors.html +168 -0
- package/docs/api/module-errors_AudioError-AudioError.html +4711 -0
- package/docs/api/module-errors_AudioError.html +178 -0
- package/docs/api/module-errors_ConnectionError-ConnectionError.html +3649 -0
- package/docs/api/module-errors_ConnectionError.html +178 -0
- package/docs/api/module-errors_CryptoError-CryptoError.html +3453 -0
- package/docs/api/module-errors_CryptoError.html +178 -0
- package/docs/api/module-errors_HandshakeError-HandshakeError.html +4261 -0
- package/docs/api/module-errors_HandshakeError.html +178 -0
- package/docs/api/module-errors_MeshError-MeshError.html +2155 -0
- package/docs/api/module-errors_MeshError.html +178 -0
- package/docs/api/module-errors_MessageError-MessageError.html +4545 -0
- package/docs/api/module-errors_MessageError.html +178 -0
- package/docs/api/module-errors_ValidationError-ValidationError.html +3432 -0
- package/docs/api/module-errors_ValidationError.html +178 -0
- package/docs/api/module-hooks.html +182 -0
- package/docs/api/module-hooks_AppStateManager-AppStateManager.html +1620 -0
- package/docs/api/module-hooks_AppStateManager.html +178 -0
- package/docs/api/module-hooks_useMesh.html +457 -0
- package/docs/api/module-hooks_useMessages.html +466 -0
- package/docs/api/module-hooks_usePeers.html +348 -0
- package/docs/api/module-mesh.html +168 -0
- package/docs/api/module-mesh_dedup.html +168 -0
- package/docs/api/module-mesh_dedup_BloomFilter-BloomFilter.html +2158 -0
- package/docs/api/module-mesh_dedup_BloomFilter.html +178 -0
- package/docs/api/module-mesh_dedup_DedupManager-DedupManager.html +2880 -0
- package/docs/api/module-mesh_dedup_DedupManager.html +178 -0
- package/docs/api/module-mesh_dedup_MessageCache-CacheNode.html +246 -0
- package/docs/api/module-mesh_dedup_MessageCache-MessageCache.html +2314 -0
- package/docs/api/module-mesh_dedup_MessageCache.html +181 -0
- package/docs/api/module-mesh_fragment.html +168 -0
- package/docs/api/module-mesh_fragment_Assembler-Assembler.html +2869 -0
- package/docs/api/module-mesh_fragment_Assembler-PendingFragmentSet.html +895 -0
- package/docs/api/module-mesh_fragment_Assembler.html +181 -0
- package/docs/api/module-mesh_fragment_Fragmenter.html +1084 -0
- package/docs/api/module-mesh_peer.html +168 -0
- package/docs/api/module-mesh_peer_Peer-Peer.html +4986 -0
- package/docs/api/module-mesh_peer_Peer.html +178 -0
- package/docs/api/module-mesh_peer_PeerDiscovery-PeerDiscovery.html +3423 -0
- package/docs/api/module-mesh_peer_PeerDiscovery.html +438 -0
- package/docs/api/module-mesh_peer_PeerManager-PeerManager.html +5258 -0
- package/docs/api/module-mesh_peer_PeerManager.html +178 -0
- package/docs/api/module-mesh_router.html +168 -0
- package/docs/api/module-mesh_router_MessageRouter-MessageRouter.html +3285 -0
- package/docs/api/module-mesh_router_MessageRouter.html +178 -0
- package/docs/api/module-mesh_router_PathFinder-PathFinder.html +3323 -0
- package/docs/api/module-mesh_router_PathFinder.html +421 -0
- package/docs/api/module-mesh_router_RouteTable-RouteTable.html +4115 -0
- package/docs/api/module-mesh_router_RouteTable.html +421 -0
- package/docs/api/module-protocol.html +169 -0
- package/docs/api/module-protocol_crc32.html +815 -0
- package/docs/api/module-protocol_deserializer.html +1393 -0
- package/docs/api/module-protocol_header-MessageHeader.html +2879 -0
- package/docs/api/module-protocol_header.html +892 -0
- package/docs/api/module-protocol_message-Message.html +4682 -0
- package/docs/api/module-protocol_message.html +178 -0
- package/docs/api/module-protocol_serializer.html +911 -0
- package/docs/api/module-protocol_validator.html +1396 -0
- package/docs/api/module-rn-ble-mesh.html +866 -0
- package/docs/api/module-service.html +168 -0
- package/docs/api/module-service_HandshakeManager-HandshakeManager.html +185 -0
- package/docs/api/module-service_HandshakeManager.html +175 -0
- package/docs/api/module-service_MeshService-MeshService.html +185 -0
- package/docs/api/module-service_MeshService.html +175 -0
- package/docs/api/module-service_SessionManager-SessionManager.html +174 -0
- package/docs/api/module-service_SessionManager.html +175 -0
- package/docs/api/module-service_audio.html +168 -0
- package/docs/api/module-service_audio_AudioManager-AudioManager.html +4653 -0
- package/docs/api/module-service_audio_AudioManager.html +254 -0
- package/docs/api/module-service_text.html +168 -0
- package/docs/api/module-service_text_TextManager-TextManager.html +6104 -0
- package/docs/api/module-service_text_TextManager.html +254 -0
- package/docs/api/module-service_text_broadcast.html +168 -0
- package/docs/api/module-service_text_broadcast_BroadcastManager-BroadcastManager.html +2434 -0
- package/docs/api/module-service_text_broadcast_BroadcastManager.html +254 -0
- package/docs/api/module-service_text_channel.html +168 -0
- package/docs/api/module-service_text_channel_Channel-Channel.html +4337 -0
- package/docs/api/module-service_text_channel_Channel.html +178 -0
- package/docs/api/module-service_text_channel_ChannelManager-ChannelManager.html +1927 -0
- package/docs/api/module-service_text_channel_ChannelManager.html +175 -0
- package/docs/api/module-service_text_message.html +168 -0
- package/docs/api/module-service_text_message_TextMessage-TextMessage.html +4162 -0
- package/docs/api/module-service_text_message_TextMessage.html +178 -0
- package/docs/api/module-service_text_message_TextSerializer.html +1725 -0
- package/docs/api/module-storage.html +168 -0
- package/docs/api/module-storage_AsyncStorageAdapter-AsyncStorageAdapter.html +4159 -0
- package/docs/api/module-storage_AsyncStorageAdapter.html +178 -0
- package/docs/api/module-storage_MemoryStorage-MemoryStorage.html +3154 -0
- package/docs/api/module-storage_MemoryStorage.html +178 -0
- package/docs/api/module-storage_MessageStore-MessageStore.html +5299 -0
- package/docs/api/module-storage_MessageStore.html +178 -0
- package/docs/api/module-storage_Storage-Storage.html +4169 -0
- package/docs/api/module-storage_Storage.html +178 -0
- package/docs/api/module-transport.html +168 -0
- package/docs/api/module-transport_BLEAdapter-BLEAdapter.html +4724 -0
- package/docs/api/module-transport_BLEAdapter.html +178 -0
- package/docs/api/module-transport_BLETransport-BLETransport.html +3263 -0
- package/docs/api/module-transport_BLETransport.html +178 -0
- package/docs/api/module-transport_MockTransport-MockTransport.html +3947 -0
- package/docs/api/module-transport_MockTransport.html +178 -0
- package/docs/api/module-transport_NodeBLEAdapter-NodeBLEAdapter.html +3216 -0
- package/docs/api/module-transport_NodeBLEAdapter.html +178 -0
- package/docs/api/module-transport_RNBLEAdapter-RNBLEAdapter.html +3216 -0
- package/docs/api/module-transport_RNBLEAdapter.html +178 -0
- package/docs/api/module-transport_Transport-Transport.html +4071 -0
- package/docs/api/module-transport_Transport.html +254 -0
- package/docs/api/module-transport_adapters.html +168 -0
- package/docs/api/module-transport_adapters_BLEAdapter-BLEAdapter.html +4724 -0
- package/docs/api/module-transport_adapters_BLEAdapter.html +178 -0
- package/docs/api/module-transport_adapters_NodeBLEAdapter-NodeBLEAdapter.html +3216 -0
- package/docs/api/module-transport_adapters_NodeBLEAdapter.html +178 -0
- package/docs/api/module-transport_adapters_RNBLEAdapter-RNBLEAdapter.html +3216 -0
- package/docs/api/module-transport_adapters_RNBLEAdapter.html +178 -0
- package/docs/api/module-utils.html +168 -0
- package/docs/api/module-utils_BoundedMap-BoundedMap.html +3301 -0
- package/docs/api/module-utils_BoundedMap.html +178 -0
- package/docs/api/module-utils_EventEmitter-EventEmitter.html +3358 -0
- package/docs/api/module-utils_EventEmitter.html +178 -0
- package/docs/api/module-utils_LRUCache-LRUCache.html +4134 -0
- package/docs/api/module-utils_LRUCache.html +178 -0
- package/docs/api/module-utils_RateLimiter-RateLimiter.html +2176 -0
- package/docs/api/module-utils_RateLimiter.html +500 -0
- package/docs/api/module-utils_TimeoutManager-TimeoutManager.html +1781 -0
- package/docs/api/module-utils_TimeoutManager.html +175 -0
- package/docs/api/module-utils_bytes.html +1789 -0
- package/docs/api/module-utils_debug.html +837 -0
- package/docs/api/module-utils_encoding.html +1184 -0
- package/docs/api/module-utils_retry.html +1457 -0
- package/docs/api/module-utils_time.html +1665 -0
- package/docs/api/module-utils_uuid.html +1269 -0
- package/docs/api/module-utils_validation.html +2176 -0
- package/docs/api/protocol_crc32.js.html +147 -0
- package/docs/api/protocol_deserializer.js.html +295 -0
- package/docs/api/protocol_header.js.html +276 -0
- package/docs/api/protocol_index.js.html +120 -0
- package/docs/api/protocol_message.js.html +287 -0
- package/docs/api/protocol_serializer.js.html +240 -0
- package/docs/api/protocol_validator.js.html +330 -0
- package/docs/api/scripts/linenumber.js +25 -0
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/prettify/lang-css.js +2 -0
- package/docs/api/scripts/prettify/prettify.js +28 -0
- package/docs/api/service_HandshakeManager.js.html +232 -0
- package/docs/api/service_MeshService.js.html +371 -0
- package/docs/api/service_SessionManager.js.html +153 -0
- package/docs/api/service_audio_AudioManager.js.html +541 -0
- package/docs/api/service_audio_buffer_FrameBuffer.js.html +223 -0
- package/docs/api/service_audio_buffer_JitterBuffer.js.html +244 -0
- package/docs/api/service_audio_buffer_index.js.html +68 -0
- package/docs/api/service_audio_codec_LC3Codec.js.html +345 -0
- package/docs/api/service_audio_codec_LC3Decoder.js.html +185 -0
- package/docs/api/service_audio_codec_LC3Encoder.js.html +194 -0
- package/docs/api/service_audio_codec_index.js.html +70 -0
- package/docs/api/service_audio_index.js.html +96 -0
- package/docs/api/service_audio_session_AudioSession.js.html +348 -0
- package/docs/api/service_audio_session_VoiceMessage.js.html +432 -0
- package/docs/api/service_audio_session_index.js.html +70 -0
- package/docs/api/service_audio_transport_AudioFragmenter.js.html +314 -0
- package/docs/api/service_audio_transport_AudioFramer.js.html +236 -0
- package/docs/api/service_audio_transport_index.js.html +69 -0
- package/docs/api/service_index.js.html +93 -0
- package/docs/api/service_text_TextManager.js.html +578 -0
- package/docs/api/service_text_broadcast_BroadcastManager.js.html +276 -0
- package/docs/api/service_text_broadcast_index.js.html +66 -0
- package/docs/api/service_text_channel_Channel.js.html +280 -0
- package/docs/api/service_text_channel_ChannelManager.js.html +225 -0
- package/docs/api/service_text_channel_index.js.html +68 -0
- package/docs/api/service_text_index.js.html +85 -0
- package/docs/api/service_text_message_TextMessage.js.html +350 -0
- package/docs/api/service_text_message_TextSerializer.js.html +218 -0
- package/docs/api/service_text_message_index.js.html +68 -0
- package/docs/api/storage_AsyncStorageAdapter.js.html +357 -0
- package/docs/api/storage_MemoryStorage.js.html +279 -0
- package/docs/api/storage_MessageStore.js.html +369 -0
- package/docs/api/storage_Storage.js.html +214 -0
- package/docs/api/storage_index.js.html +72 -0
- package/docs/api/styles/jsdoc-default.css +358 -0
- package/docs/api/styles/prettify-jsdoc.css +111 -0
- package/docs/api/styles/prettify-tomorrow.css +132 -0
- package/docs/api/transport_BLEAdapter.js.html +231 -0
- package/docs/api/transport_BLETransport.js.html +411 -0
- package/docs/api/transport_MockTransport.js.html +339 -0
- package/docs/api/transport_NodeBLEAdapter.js.html +479 -0
- package/docs/api/transport_RNBLEAdapter.js.html +382 -0
- package/docs/api/transport_Transport.js.html +242 -0
- package/docs/api/transport_adapters_BLEAdapter.js.html +231 -0
- package/docs/api/transport_adapters_NodeBLEAdapter.js.html +479 -0
- package/docs/api/transport_adapters_RNBLEAdapter.js.html +382 -0
- package/docs/api/transport_adapters_index.js.html +70 -0
- package/docs/api/transport_index.js.html +87 -0
- package/docs/api/utils_BoundedMap.js.html +205 -0
- package/docs/api/utils_EventEmitter.js.html +259 -0
- package/docs/api/utils_LRUCache.js.html +256 -0
- package/docs/api/utils_RateLimiter.js.html +256 -0
- package/docs/api/utils_TimeoutManager.js.html +218 -0
- package/docs/api/utils_base64%0A%0AThis%20implementation%20avoids%20string%20concatenation%20in%20loops%20which%20is%20O(n%C2%B2).%0AUses%20array%20building%20which%20is%20O(n)%20-%20critical%20for%20React%20Native%20performance.module_.html +717 -0
- package/docs/api/utils_base64.js.html +205 -0
- package/docs/api/utils_bytes.js.html +241 -0
- package/docs/api/utils_debug.js.html +205 -0
- package/docs/api/utils_encoding.js.html +302 -0
- package/docs/api/utils_index.js.html +160 -0
- package/docs/api/utils_retry.js.html +200 -0
- package/docs/api/utils_time.js.html +220 -0
- package/docs/api/utils_uuid.js.html +199 -0
- package/docs/api/utils_validation.js.html +259 -0
- package/examples/node-chat/chat.js +220 -0
- package/examples/node-quickstart/index.js +94 -0
- package/examples/testing/test-helper.js +182 -0
- package/package.json +111 -0
- package/src/constants/audio.js +130 -0
- package/src/constants/ble.js +111 -0
- package/src/constants/crypto.js +53 -0
- package/src/constants/errors.js +202 -0
- package/src/constants/events.js +94 -0
- package/src/constants/index.js +22 -0
- package/src/constants/protocol.js +151 -0
- package/src/crypto/aead.js +189 -0
- package/src/crypto/chacha20.js +181 -0
- package/src/crypto/hkdf.js +187 -0
- package/src/crypto/hmac.js +143 -0
- package/src/crypto/index.js +72 -0
- package/src/crypto/keys/KeyManager.js +271 -0
- package/src/crypto/keys/KeyPair.js +216 -0
- package/src/crypto/keys/SecureStorage.js +219 -0
- package/src/crypto/keys/index.js +32 -0
- package/src/crypto/noise/handshake.js +410 -0
- package/src/crypto/noise/index.js +27 -0
- package/src/crypto/noise/session.js +253 -0
- package/src/crypto/noise/state.js +268 -0
- package/src/crypto/poly1305.js +113 -0
- package/src/crypto/sha256.js +240 -0
- package/src/crypto/x25519.js +154 -0
- package/src/errors/AudioError.js +164 -0
- package/src/errors/ConnectionError.js +109 -0
- package/src/errors/CryptoError.js +103 -0
- package/src/errors/HandshakeError.js +122 -0
- package/src/errors/MeshError.js +100 -0
- package/src/errors/MessageError.js +129 -0
- package/src/errors/ValidationError.js +150 -0
- package/src/errors/index.js +24 -0
- package/src/hooks/AppStateManager.js +179 -0
- package/src/hooks/index.js +33 -0
- package/src/hooks/useMesh.js +159 -0
- package/src/hooks/useMessages.js +209 -0
- package/src/hooks/usePeers.js +111 -0
- package/src/index.d.ts +494 -0
- package/src/index.js +182 -0
- package/src/index.mjs +62 -0
- package/src/mesh/dedup/BloomFilter.js +207 -0
- package/src/mesh/dedup/DedupManager.js +212 -0
- package/src/mesh/dedup/MessageCache.js +219 -0
- package/src/mesh/dedup/index.js +16 -0
- package/src/mesh/fragment/Assembler.js +281 -0
- package/src/mesh/fragment/Fragmenter.js +176 -0
- package/src/mesh/fragment/index.js +21 -0
- package/src/mesh/index.js +18 -0
- package/src/mesh/peer/Peer.js +242 -0
- package/src/mesh/peer/PeerDiscovery.js +280 -0
- package/src/mesh/peer/PeerManager.js +266 -0
- package/src/mesh/peer/index.js +16 -0
- package/src/mesh/router/MessageRouter.js +357 -0
- package/src/mesh/router/PathFinder.js +332 -0
- package/src/mesh/router/RouteTable.js +292 -0
- package/src/mesh/router/index.js +16 -0
- package/src/protocol/crc32.js +93 -0
- package/src/protocol/deserializer.js +241 -0
- package/src/protocol/header.js +222 -0
- package/src/protocol/index.js +66 -0
- package/src/protocol/message.js +233 -0
- package/src/protocol/serializer.js +186 -0
- package/src/protocol/validator.js +276 -0
- package/src/service/HandshakeManager.js +178 -0
- package/src/service/MeshService.js +317 -0
- package/src/service/SessionManager.js +99 -0
- package/src/service/audio/AudioManager.js +487 -0
- package/src/service/audio/buffer/FrameBuffer.js +169 -0
- package/src/service/audio/buffer/JitterBuffer.js +190 -0
- package/src/service/audio/buffer/index.js +14 -0
- package/src/service/audio/codec/LC3Codec.js +291 -0
- package/src/service/audio/codec/LC3Decoder.js +131 -0
- package/src/service/audio/codec/LC3Encoder.js +140 -0
- package/src/service/audio/codec/index.js +16 -0
- package/src/service/audio/index.js +42 -0
- package/src/service/audio/session/AudioSession.js +294 -0
- package/src/service/audio/session/VoiceMessage.js +378 -0
- package/src/service/audio/session/index.js +16 -0
- package/src/service/audio/transport/AudioFragmenter.js +260 -0
- package/src/service/audio/transport/AudioFramer.js +182 -0
- package/src/service/audio/transport/index.js +15 -0
- package/src/service/index.js +39 -0
- package/src/service/text/TextManager.js +524 -0
- package/src/service/text/broadcast/BroadcastManager.js +222 -0
- package/src/service/text/broadcast/index.js +12 -0
- package/src/service/text/channel/Channel.js +226 -0
- package/src/service/text/channel/ChannelManager.js +171 -0
- package/src/service/text/channel/index.js +14 -0
- package/src/service/text/index.js +31 -0
- package/src/service/text/message/TextMessage.js +296 -0
- package/src/service/text/message/TextSerializer.js +164 -0
- package/src/service/text/message/index.js +14 -0
- package/src/storage/AsyncStorageAdapter.js +303 -0
- package/src/storage/MemoryStorage.js +225 -0
- package/src/storage/MessageStore.js +315 -0
- package/src/storage/Storage.js +160 -0
- package/src/storage/index.js +18 -0
- package/src/transport/BLEAdapter.js +177 -0
- package/src/transport/BLETransport.js +357 -0
- package/src/transport/MockTransport.js +285 -0
- package/src/transport/NodeBLEAdapter.js +425 -0
- package/src/transport/RNBLEAdapter.js +328 -0
- package/src/transport/Transport.js +188 -0
- package/src/transport/adapters/BLEAdapter.js +177 -0
- package/src/transport/adapters/NodeBLEAdapter.js +425 -0
- package/src/transport/adapters/RNBLEAdapter.js +328 -0
- package/src/transport/adapters/index.js +16 -0
- package/src/transport/index.js +33 -0
- package/src/utils/BoundedMap.js +151 -0
- package/src/utils/EventEmitter.js +205 -0
- package/src/utils/LRUCache.js +202 -0
- package/src/utils/RateLimiter.js +202 -0
- package/src/utils/TimeoutManager.js +164 -0
- package/src/utils/base64.js +151 -0
- package/src/utils/bytes.js +187 -0
- package/src/utils/debug.js +151 -0
- package/src/utils/encoding.js +248 -0
- package/src/utils/index.js +106 -0
- package/src/utils/retry.js +146 -0
- package/src/utils/time.js +166 -0
- package/src/utils/uuid.js +145 -0
- package/src/utils/validation.js +205 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Noise Protocol Transport Session
|
|
5
|
+
* Handles encrypted communication after a successful handshake.
|
|
6
|
+
* @module crypto/noise/session
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { encrypt, decrypt } = require('../aead');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Maximum nonce value before requiring rekey (2^64 - 1 as safe integer)
|
|
13
|
+
* In practice, we use a lower limit to ensure safety
|
|
14
|
+
* @constant {number}
|
|
15
|
+
*/
|
|
16
|
+
const MAX_NONCE = Number.MAX_SAFE_INTEGER;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Nonce threshold for rekey warning
|
|
20
|
+
* @constant {number}
|
|
21
|
+
*/
|
|
22
|
+
const REKEY_THRESHOLD = 0xFFFFFFFF; // 2^32 - 1
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* NoiseSession handles encrypted transport after handshake completion.
|
|
26
|
+
*
|
|
27
|
+
* Each direction has its own key and nonce counter:
|
|
28
|
+
* - sendKey/sendNonce for outgoing messages
|
|
29
|
+
* - receiveKey/receiveNonce for incoming messages
|
|
30
|
+
*
|
|
31
|
+
* @class
|
|
32
|
+
*/
|
|
33
|
+
class NoiseSession {
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new NoiseSession.
|
|
36
|
+
* @param {Uint8Array} sendKey - 32-byte key for sending
|
|
37
|
+
* @param {Uint8Array} receiveKey - 32-byte key for receiving
|
|
38
|
+
* @param {boolean} isInitiator - True if this is the initiator's session
|
|
39
|
+
*/
|
|
40
|
+
constructor(sendKey, receiveKey, isInitiator) {
|
|
41
|
+
if (!(sendKey instanceof Uint8Array) || sendKey.length !== 32) {
|
|
42
|
+
throw new Error('Send key must be 32 bytes');
|
|
43
|
+
}
|
|
44
|
+
if (!(receiveKey instanceof Uint8Array) || receiveKey.length !== 32) {
|
|
45
|
+
throw new Error('Receive key must be 32 bytes');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @type {Uint8Array} */
|
|
49
|
+
this._sendKey = new Uint8Array(sendKey);
|
|
50
|
+
|
|
51
|
+
/** @type {Uint8Array} */
|
|
52
|
+
this._receiveKey = new Uint8Array(receiveKey);
|
|
53
|
+
|
|
54
|
+
/** @type {number} */
|
|
55
|
+
this._sendNonce = 0;
|
|
56
|
+
|
|
57
|
+
/** @type {number} */
|
|
58
|
+
this._receiveNonce = 0;
|
|
59
|
+
|
|
60
|
+
/** @type {boolean} */
|
|
61
|
+
this._isInitiator = isInitiator;
|
|
62
|
+
|
|
63
|
+
/** @type {boolean} */
|
|
64
|
+
this._established = true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets the current send nonce.
|
|
69
|
+
* @returns {number} Current send nonce value
|
|
70
|
+
*/
|
|
71
|
+
get sendNonce() {
|
|
72
|
+
return this._sendNonce;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets the current receive nonce.
|
|
77
|
+
* @returns {number} Current receive nonce value
|
|
78
|
+
*/
|
|
79
|
+
get receiveNonce() {
|
|
80
|
+
return this._receiveNonce;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Encrypts a message for sending.
|
|
85
|
+
* @param {Uint8Array} plaintext - Message to encrypt
|
|
86
|
+
* @returns {Uint8Array} Encrypted message with authentication tag
|
|
87
|
+
* @throws {Error} If nonce overflow or session not established
|
|
88
|
+
*/
|
|
89
|
+
encrypt(plaintext) {
|
|
90
|
+
if (!this._established) {
|
|
91
|
+
throw new Error('Session not established');
|
|
92
|
+
}
|
|
93
|
+
if (!(plaintext instanceof Uint8Array)) {
|
|
94
|
+
throw new Error('Plaintext must be a Uint8Array');
|
|
95
|
+
}
|
|
96
|
+
if (this._sendNonce >= MAX_NONCE) {
|
|
97
|
+
throw new Error('Send nonce overflow - session must be rekeyed');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const nonce = this._createNonce(this._sendNonce);
|
|
101
|
+
this._sendNonce++;
|
|
102
|
+
|
|
103
|
+
// Warn if approaching nonce limit
|
|
104
|
+
if (this._sendNonce === REKEY_THRESHOLD) {
|
|
105
|
+
console.warn('NoiseSession: Approaching send nonce limit, rekey recommended');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return encrypt(this._sendKey, nonce, plaintext);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Decrypts a received message.
|
|
113
|
+
* @param {Uint8Array} ciphertext - Encrypted message with authentication tag
|
|
114
|
+
* @returns {Uint8Array|null} Decrypted plaintext, or null if authentication fails
|
|
115
|
+
* @throws {Error} If nonce overflow or session not established
|
|
116
|
+
*/
|
|
117
|
+
decrypt(ciphertext) {
|
|
118
|
+
if (!this._established) {
|
|
119
|
+
throw new Error('Session not established');
|
|
120
|
+
}
|
|
121
|
+
if (!(ciphertext instanceof Uint8Array)) {
|
|
122
|
+
throw new Error('Ciphertext must be a Uint8Array');
|
|
123
|
+
}
|
|
124
|
+
if (ciphertext.length < 16) {
|
|
125
|
+
throw new Error('Ciphertext too short (minimum 16 bytes for tag)');
|
|
126
|
+
}
|
|
127
|
+
if (this._receiveNonce >= MAX_NONCE) {
|
|
128
|
+
throw new Error('Receive nonce overflow - session must be rekeyed');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const nonce = this._createNonce(this._receiveNonce);
|
|
132
|
+
const plaintext = decrypt(this._receiveKey, nonce, ciphertext);
|
|
133
|
+
|
|
134
|
+
if (plaintext !== null) {
|
|
135
|
+
this._receiveNonce++;
|
|
136
|
+
|
|
137
|
+
// Warn if approaching nonce limit
|
|
138
|
+
if (this._receiveNonce === REKEY_THRESHOLD) {
|
|
139
|
+
console.warn('NoiseSession: Approaching receive nonce limit, rekey recommended');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return plaintext;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks if the session is established and ready for use.
|
|
148
|
+
* @returns {boolean} True if session is established
|
|
149
|
+
*/
|
|
150
|
+
isEstablished() {
|
|
151
|
+
return this._established;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Exports the session state for persistence.
|
|
156
|
+
* WARNING: Contains sensitive key material, handle with care.
|
|
157
|
+
* @returns {object} Session state object
|
|
158
|
+
*/
|
|
159
|
+
exportState() {
|
|
160
|
+
return {
|
|
161
|
+
sendKey: Array.from(this._sendKey),
|
|
162
|
+
receiveKey: Array.from(this._receiveKey),
|
|
163
|
+
sendNonce: this._sendNonce,
|
|
164
|
+
receiveNonce: this._receiveNonce,
|
|
165
|
+
isInitiator: this._isInitiator,
|
|
166
|
+
established: this._established
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Creates a NoiseSession from exported state.
|
|
172
|
+
* @param {object} state - Previously exported session state
|
|
173
|
+
* @returns {NoiseSession} Restored session
|
|
174
|
+
* @throws {Error} If state is invalid
|
|
175
|
+
*/
|
|
176
|
+
static importState(state) {
|
|
177
|
+
if (!state || typeof state !== 'object') {
|
|
178
|
+
throw new Error('Invalid session state');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const requiredFields = [
|
|
182
|
+
'sendKey', 'receiveKey', 'sendNonce', 'receiveNonce', 'isInitiator'
|
|
183
|
+
];
|
|
184
|
+
for (const field of requiredFields) {
|
|
185
|
+
if (!(field in state)) {
|
|
186
|
+
throw new Error(`Missing required field: ${field}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const sendKey = new Uint8Array(state.sendKey);
|
|
191
|
+
const receiveKey = new Uint8Array(state.receiveKey);
|
|
192
|
+
|
|
193
|
+
if (sendKey.length !== 32 || receiveKey.length !== 32) {
|
|
194
|
+
throw new Error('Invalid key length in state');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const session = new NoiseSession(sendKey, receiveKey, state.isInitiator);
|
|
198
|
+
session._sendNonce = state.sendNonce;
|
|
199
|
+
session._receiveNonce = state.receiveNonce;
|
|
200
|
+
session._established = state.established !== false;
|
|
201
|
+
|
|
202
|
+
return session;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Destroys the session, zeroing sensitive key material.
|
|
207
|
+
*/
|
|
208
|
+
destroy() {
|
|
209
|
+
this._sendKey.fill(0);
|
|
210
|
+
this._receiveKey.fill(0);
|
|
211
|
+
this._sendNonce = 0;
|
|
212
|
+
this._receiveNonce = 0;
|
|
213
|
+
this._established = false;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Creates a 12-byte nonce from a counter value.
|
|
218
|
+
* Format: 4 zero bytes + 8-byte little-endian counter
|
|
219
|
+
* @param {number} counter - Nonce counter value
|
|
220
|
+
* @returns {Uint8Array} 12-byte nonce
|
|
221
|
+
* @private
|
|
222
|
+
*/
|
|
223
|
+
_createNonce(counter) {
|
|
224
|
+
const nonce = new Uint8Array(12);
|
|
225
|
+
const view = new DataView(nonce.buffer);
|
|
226
|
+
// First 4 bytes are zero
|
|
227
|
+
// Next 8 bytes are little-endian counter
|
|
228
|
+
view.setUint32(4, counter >>> 0, true);
|
|
229
|
+
view.setUint32(8, Math.floor(counter / 0x100000000) >>> 0, true);
|
|
230
|
+
return nonce;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Gets session statistics.
|
|
235
|
+
* @returns {object} Session statistics
|
|
236
|
+
*/
|
|
237
|
+
getStats() {
|
|
238
|
+
return {
|
|
239
|
+
messagesSent: this._sendNonce,
|
|
240
|
+
messagesReceived: this._receiveNonce,
|
|
241
|
+
isInitiator: this._isInitiator,
|
|
242
|
+
established: this._established,
|
|
243
|
+
sendNonceRemaining: MAX_NONCE - this._sendNonce,
|
|
244
|
+
receiveNonceRemaining: MAX_NONCE - this._receiveNonce
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = {
|
|
250
|
+
NoiseSession,
|
|
251
|
+
MAX_NONCE,
|
|
252
|
+
REKEY_THRESHOLD
|
|
253
|
+
};
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Noise Protocol Symmetric State
|
|
5
|
+
* Implements the symmetric cryptographic state for Noise Protocol handshakes.
|
|
6
|
+
* @module crypto/noise/state
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { hash } = require('../sha256');
|
|
10
|
+
const { encrypt, decrypt } = require('../aead');
|
|
11
|
+
const { concat } = require('../../utils/bytes');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Protocol name for Noise_XX_25519_ChaChaPoly_SHA256
|
|
15
|
+
* @constant {string}
|
|
16
|
+
*/
|
|
17
|
+
const PROTOCOL_NAME = 'Noise_XX_25519_ChaChaPoly_SHA256';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Maximum nonce value before overflow (2^64 - 1 represented as safe integer)
|
|
21
|
+
* @constant {number}
|
|
22
|
+
*/
|
|
23
|
+
const MAX_NONCE = Number.MAX_SAFE_INTEGER;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* SymmetricState manages the cryptographic state during a Noise handshake.
|
|
27
|
+
*
|
|
28
|
+
* Properties:
|
|
29
|
+
* - h: Handshake hash (32 bytes) - rolling hash of all handshake data
|
|
30
|
+
* - ck: Chaining key (32 bytes) - for key derivation
|
|
31
|
+
* - k: Cipher key (32 bytes or null) - for encrypting handshake payloads
|
|
32
|
+
* - n: Nonce counter - increments with each encryption
|
|
33
|
+
*
|
|
34
|
+
* @class
|
|
35
|
+
*/
|
|
36
|
+
class SymmetricState {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new SymmetricState.
|
|
39
|
+
* @param {string} [protocolName=PROTOCOL_NAME] - The Noise protocol name
|
|
40
|
+
*/
|
|
41
|
+
constructor(protocolName = PROTOCOL_NAME) {
|
|
42
|
+
const nameBytes = new TextEncoder().encode(protocolName);
|
|
43
|
+
|
|
44
|
+
// If protocol name is <= 32 bytes, pad with zeros
|
|
45
|
+
// If > 32 bytes, hash it
|
|
46
|
+
if (nameBytes.length <= 32) {
|
|
47
|
+
this._h = new Uint8Array(32);
|
|
48
|
+
this._h.set(nameBytes);
|
|
49
|
+
} else {
|
|
50
|
+
this._h = hash(nameBytes);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Initialize chaining key to handshake hash
|
|
54
|
+
this._ck = new Uint8Array(this._h);
|
|
55
|
+
|
|
56
|
+
// Cipher key starts as null (no encryption until first MixKey)
|
|
57
|
+
this._k = null;
|
|
58
|
+
|
|
59
|
+
// Nonce counter
|
|
60
|
+
this._n = 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the current handshake hash.
|
|
65
|
+
* @returns {Uint8Array} Copy of the handshake hash
|
|
66
|
+
*/
|
|
67
|
+
get h() {
|
|
68
|
+
return new Uint8Array(this._h);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Gets the current chaining key.
|
|
73
|
+
* @returns {Uint8Array} Copy of the chaining key
|
|
74
|
+
*/
|
|
75
|
+
get ck() {
|
|
76
|
+
return new Uint8Array(this._ck);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets the current cipher key.
|
|
81
|
+
* @returns {Uint8Array|null} Copy of cipher key or null
|
|
82
|
+
*/
|
|
83
|
+
get k() {
|
|
84
|
+
return this._k ? new Uint8Array(this._k) : null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the current nonce.
|
|
89
|
+
* @returns {number} Current nonce value
|
|
90
|
+
*/
|
|
91
|
+
get n() {
|
|
92
|
+
return this._n;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* MixHash: Updates handshake hash with new data.
|
|
97
|
+
* h = SHA256(h || data)
|
|
98
|
+
*
|
|
99
|
+
* @param {Uint8Array} data - Data to mix into the hash
|
|
100
|
+
*/
|
|
101
|
+
mixHash(data) {
|
|
102
|
+
this._h = hash(concat(this._h, data));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* MixKey: Derives new chaining key and cipher key from input key material.
|
|
107
|
+
* Uses HKDF with current chaining key as salt.
|
|
108
|
+
*
|
|
109
|
+
* (ck, k) = HKDF(ck, inputKeyMaterial)
|
|
110
|
+
* Resets nonce to 0.
|
|
111
|
+
*
|
|
112
|
+
* @param {Uint8Array} inputKeyMaterial - Key material to mix in (e.g., DH result)
|
|
113
|
+
*/
|
|
114
|
+
mixKey(inputKeyMaterial) {
|
|
115
|
+
// Use proper HKDF: extract then expand
|
|
116
|
+
const tempKey = hash(concat(this._ck, inputKeyMaterial));
|
|
117
|
+
const derived = this._hkdfDeriveKeys(tempKey);
|
|
118
|
+
|
|
119
|
+
this._ck = derived.ck;
|
|
120
|
+
this._k = derived.k;
|
|
121
|
+
this._n = 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Internal HKDF key derivation for MixKey.
|
|
126
|
+
* @param {Uint8Array} tempKey - Temporary key from HKDF-Extract
|
|
127
|
+
* @returns {{ck: Uint8Array, k: Uint8Array}} Derived keys
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
_hkdfDeriveKeys(tempKey) {
|
|
131
|
+
// T1 = HMAC(tempKey, 0x01)
|
|
132
|
+
const t1Input = new Uint8Array(1);
|
|
133
|
+
t1Input[0] = 0x01;
|
|
134
|
+
const { hmacSha256 } = require('../hmac');
|
|
135
|
+
const ck = hmacSha256(tempKey, t1Input);
|
|
136
|
+
|
|
137
|
+
// T2 = HMAC(tempKey, T1 || 0x02)
|
|
138
|
+
const t2Input = new Uint8Array(33);
|
|
139
|
+
t2Input.set(ck);
|
|
140
|
+
t2Input[32] = 0x02;
|
|
141
|
+
const k = hmacSha256(tempKey, t2Input);
|
|
142
|
+
|
|
143
|
+
return { ck, k };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* EncryptAndHash: Encrypts plaintext and mixes ciphertext into hash.
|
|
148
|
+
* If no cipher key is set, returns plaintext unchanged.
|
|
149
|
+
*
|
|
150
|
+
* @param {Uint8Array} plaintext - Data to encrypt
|
|
151
|
+
* @returns {Uint8Array} Ciphertext (or plaintext if k is null)
|
|
152
|
+
* @throws {Error} If nonce overflows
|
|
153
|
+
*/
|
|
154
|
+
encryptAndHash(plaintext) {
|
|
155
|
+
if (this._k === null) {
|
|
156
|
+
// No key yet, just mix plaintext into hash
|
|
157
|
+
this.mixHash(plaintext);
|
|
158
|
+
return plaintext;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (this._n >= MAX_NONCE) {
|
|
162
|
+
throw new Error('Nonce overflow');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Create 12-byte nonce: 4 zero bytes + 8-byte little-endian counter
|
|
166
|
+
const nonce = this._createNonce(this._n);
|
|
167
|
+
this._n++;
|
|
168
|
+
|
|
169
|
+
// Encrypt with h as AAD
|
|
170
|
+
const ciphertext = encrypt(this._k, nonce, plaintext, this._h);
|
|
171
|
+
|
|
172
|
+
// Mix ciphertext into hash
|
|
173
|
+
this.mixHash(ciphertext);
|
|
174
|
+
|
|
175
|
+
return ciphertext;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* DecryptAndHash: Decrypts ciphertext and mixes it into hash.
|
|
180
|
+
* If no cipher key is set, returns ciphertext unchanged.
|
|
181
|
+
*
|
|
182
|
+
* @param {Uint8Array} ciphertext - Data to decrypt
|
|
183
|
+
* @returns {Uint8Array} Plaintext (or ciphertext if k is null)
|
|
184
|
+
* @throws {Error} If decryption fails or nonce overflows
|
|
185
|
+
*/
|
|
186
|
+
decryptAndHash(ciphertext) {
|
|
187
|
+
if (this._k === null) {
|
|
188
|
+
// No key yet, just mix ciphertext into hash
|
|
189
|
+
this.mixHash(ciphertext);
|
|
190
|
+
return ciphertext;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (this._n >= MAX_NONCE) {
|
|
194
|
+
throw new Error('Nonce overflow');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Create 12-byte nonce
|
|
198
|
+
const nonce = this._createNonce(this._n);
|
|
199
|
+
this._n++;
|
|
200
|
+
|
|
201
|
+
// Decrypt with h as AAD
|
|
202
|
+
const plaintext = decrypt(this._k, nonce, ciphertext, this._h);
|
|
203
|
+
|
|
204
|
+
if (plaintext === null) {
|
|
205
|
+
throw new Error('Decryption failed: authentication error');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Mix ciphertext into hash (not plaintext!)
|
|
209
|
+
this.mixHash(ciphertext);
|
|
210
|
+
|
|
211
|
+
return plaintext;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Split: Derives final transport keys from the handshake state.
|
|
216
|
+
* Returns two keys for bidirectional communication.
|
|
217
|
+
*
|
|
218
|
+
* @returns {{sendKey: Uint8Array, receiveKey: Uint8Array}} Transport keys
|
|
219
|
+
*/
|
|
220
|
+
split() {
|
|
221
|
+
const tempKey = hash(concat(this._ck, new Uint8Array(0)));
|
|
222
|
+
const { hmacSha256 } = require('../hmac');
|
|
223
|
+
|
|
224
|
+
// k1 = HKDF-Expand(ck, 0x01)
|
|
225
|
+
const t1Input = new Uint8Array(1);
|
|
226
|
+
t1Input[0] = 0x01;
|
|
227
|
+
const k1 = hmacSha256(tempKey, t1Input);
|
|
228
|
+
|
|
229
|
+
// k2 = HKDF-Expand(ck, k1 || 0x02)
|
|
230
|
+
const t2Input = new Uint8Array(33);
|
|
231
|
+
t2Input.set(k1);
|
|
232
|
+
t2Input[32] = 0x02;
|
|
233
|
+
const k2 = hmacSha256(tempKey, t2Input);
|
|
234
|
+
|
|
235
|
+
return { sendKey: k1, receiveKey: k2 };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Gets a copy of the current handshake hash.
|
|
240
|
+
* @returns {Uint8Array} Copy of handshake hash
|
|
241
|
+
*/
|
|
242
|
+
getHandshakeHash() {
|
|
243
|
+
return new Uint8Array(this._h);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Creates a 12-byte nonce from a counter value.
|
|
248
|
+
* Format: 4 zero bytes + 8-byte little-endian counter
|
|
249
|
+
*
|
|
250
|
+
* @param {number} counter - Nonce counter value
|
|
251
|
+
* @returns {Uint8Array} 12-byte nonce
|
|
252
|
+
* @private
|
|
253
|
+
*/
|
|
254
|
+
_createNonce(counter) {
|
|
255
|
+
const nonce = new Uint8Array(12);
|
|
256
|
+
const view = new DataView(nonce.buffer);
|
|
257
|
+
// First 4 bytes are zero
|
|
258
|
+
// Next 8 bytes are little-endian counter
|
|
259
|
+
view.setUint32(4, counter >>> 0, true);
|
|
260
|
+
view.setUint32(8, Math.floor(counter / 0x100000000) >>> 0, true);
|
|
261
|
+
return nonce;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
SymmetricState,
|
|
267
|
+
PROTOCOL_NAME
|
|
268
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Poly1305 message authentication code (RFC 8439)
|
|
3
|
+
* @module crypto/poly1305
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Clamps the r portion of the Poly1305 key per RFC 8439
|
|
10
|
+
* Clears bits 4,5,6,7 of bytes 3,7,11,15 and bits 0,1 of bytes 4,8,12
|
|
11
|
+
* @param {Uint8Array} r - 16-byte r value (modified in place)
|
|
12
|
+
* @returns {Uint8Array} Clamped r value
|
|
13
|
+
*/
|
|
14
|
+
function clamp(r) {
|
|
15
|
+
r[3] &= 0x0f;
|
|
16
|
+
r[7] &= 0x0f;
|
|
17
|
+
r[11] &= 0x0f;
|
|
18
|
+
r[15] &= 0x0f;
|
|
19
|
+
r[4] &= 0xfc;
|
|
20
|
+
r[8] &= 0xfc;
|
|
21
|
+
r[12] &= 0xfc;
|
|
22
|
+
return r;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Converts bytes to BigInt (little-endian)
|
|
27
|
+
* @param {Uint8Array} bytes - Byte array
|
|
28
|
+
* @returns {bigint} BigInt value
|
|
29
|
+
*/
|
|
30
|
+
function bytesToBigInt(bytes) {
|
|
31
|
+
let result = 0n;
|
|
32
|
+
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
33
|
+
result = (result << 8n) | BigInt(bytes[i]);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Converts BigInt to bytes (little-endian)
|
|
40
|
+
* @param {bigint} num - BigInt value
|
|
41
|
+
* @param {number} length - Desired byte length
|
|
42
|
+
* @returns {Uint8Array} Byte array
|
|
43
|
+
*/
|
|
44
|
+
function bigIntToBytes(num, length) {
|
|
45
|
+
const bytes = new Uint8Array(length);
|
|
46
|
+
let value = num;
|
|
47
|
+
for (let i = 0; i < length; i++) {
|
|
48
|
+
bytes[i] = Number(value & 0xffn);
|
|
49
|
+
value >>= 8n;
|
|
50
|
+
}
|
|
51
|
+
return bytes;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Computes Poly1305 MAC
|
|
56
|
+
* @param {Uint8Array} key - 32-byte one-time key
|
|
57
|
+
* @param {Uint8Array} message - Message to authenticate
|
|
58
|
+
* @returns {Uint8Array} 16-byte authentication tag
|
|
59
|
+
* @throws {Error} If key is not 32 bytes
|
|
60
|
+
*/
|
|
61
|
+
function poly1305(key, message) {
|
|
62
|
+
if (!(key instanceof Uint8Array) || key.length !== 32) {
|
|
63
|
+
throw new Error('Key must be 32 bytes');
|
|
64
|
+
}
|
|
65
|
+
if (!(message instanceof Uint8Array)) {
|
|
66
|
+
throw new Error('Message must be a Uint8Array');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Split key into r and s
|
|
70
|
+
const r = new Uint8Array(key.subarray(0, 16));
|
|
71
|
+
const s = key.subarray(16, 32);
|
|
72
|
+
|
|
73
|
+
// Clamp r
|
|
74
|
+
clamp(r);
|
|
75
|
+
|
|
76
|
+
// Convert to BigInt
|
|
77
|
+
const rBig = bytesToBigInt(r);
|
|
78
|
+
const sBig = bytesToBigInt(s);
|
|
79
|
+
|
|
80
|
+
// Prime p = 2^130 - 5
|
|
81
|
+
const p = (1n << 130n) - 5n;
|
|
82
|
+
|
|
83
|
+
// Process message in 16-byte blocks
|
|
84
|
+
let accumulator = 0n;
|
|
85
|
+
const numBlocks = Math.ceil(message.length / 16);
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
88
|
+
const start = i * 16;
|
|
89
|
+
const end = Math.min(start + 16, message.length);
|
|
90
|
+
const blockSize = end - start;
|
|
91
|
+
|
|
92
|
+
// Create block with appended 0x01 byte
|
|
93
|
+
const block = new Uint8Array(blockSize + 1);
|
|
94
|
+
block.set(message.subarray(start, end));
|
|
95
|
+
block[blockSize] = 0x01;
|
|
96
|
+
|
|
97
|
+
// Convert block to number and add to accumulator
|
|
98
|
+
const n = bytesToBigInt(block);
|
|
99
|
+
accumulator = (accumulator + n) % p;
|
|
100
|
+
|
|
101
|
+
// Multiply by r
|
|
102
|
+
accumulator = (accumulator * rBig) % p;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add s (no reduction mod p)
|
|
106
|
+
const tag = (accumulator + sBig) % (1n << 128n);
|
|
107
|
+
|
|
108
|
+
return bigIntToBytes(tag, 16);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = {
|
|
112
|
+
poly1305
|
|
113
|
+
};
|