mirror of
https://github.com/varun-r-mallya/py-libp2p.git
synced 2026-02-12 16:10:57 +00:00
fix: add QUICTLSSecurityConfig for better security config handle
This commit is contained in:
@ -11,6 +11,7 @@ import sys
|
|||||||
import trio
|
import trio
|
||||||
|
|
||||||
from libp2p.crypto.ed25519 import create_new_key_pair
|
from libp2p.crypto.ed25519 import create_new_key_pair
|
||||||
|
from libp2p.transport.quic.security import LIBP2P_TLS_EXTENSION_OID
|
||||||
from libp2p.transport.quic.transport import QUICTransport, QUICTransportConfig
|
from libp2p.transport.quic.transport import QUICTransport, QUICTransportConfig
|
||||||
from libp2p.transport.quic.utils import create_quic_multiaddr
|
from libp2p.transport.quic.utils import create_quic_multiaddr
|
||||||
|
|
||||||
@ -59,11 +60,10 @@ async def test_certificate_generation():
|
|||||||
# Check for libp2p extension
|
# Check for libp2p extension
|
||||||
has_libp2p_ext = False
|
has_libp2p_ext = False
|
||||||
for ext in cert.extensions:
|
for ext in cert.extensions:
|
||||||
if str(ext.oid) == "1.3.6.1.4.1.53594.1.1":
|
if ext.oid == LIBP2P_TLS_EXTENSION_OID:
|
||||||
has_libp2p_ext = True
|
has_libp2p_ext = True
|
||||||
print(f"✅ Found libp2p extension: {ext.oid}")
|
print(f"✅ Found libp2p extension: {ext.oid}")
|
||||||
print(f"Extension critical: {ext.critical}")
|
print(f"Extension critical: {ext.critical}")
|
||||||
print(f"Extension value length: {len(ext.value)} bytes")
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if not has_libp2p_ext:
|
if not has_libp2p_ext:
|
||||||
@ -209,7 +209,7 @@ async def test_server_startup():
|
|||||||
# Check for libp2p extension
|
# Check for libp2p extension
|
||||||
has_libp2p_ext = False
|
has_libp2p_ext = False
|
||||||
for ext in cert.extensions:
|
for ext in cert.extensions:
|
||||||
if str(ext.oid) == "1.3.6.1.4.1.53594.1.1":
|
if ext.oid == LIBP2P_TLS_EXTENSION_OID:
|
||||||
has_libp2p_ext = True
|
has_libp2p_ext = True
|
||||||
break
|
break
|
||||||
print(f"Has libp2p extension: {has_libp2p_ext}")
|
print(f"Has libp2p extension: {has_libp2p_ext}")
|
||||||
|
|||||||
@ -17,7 +17,10 @@ import trio
|
|||||||
|
|
||||||
from libp2p.abc import IListener
|
from libp2p.abc import IListener
|
||||||
from libp2p.custom_types import THandler, TProtocol
|
from libp2p.custom_types import THandler, TProtocol
|
||||||
from libp2p.transport.quic.security import QUICTLSConfigManager
|
from libp2p.transport.quic.security import (
|
||||||
|
LIBP2P_TLS_EXTENSION_OID,
|
||||||
|
QUICTLSConfigManager,
|
||||||
|
)
|
||||||
|
|
||||||
from .config import QUICTransportConfig
|
from .config import QUICTransportConfig
|
||||||
from .connection import QUICConnection
|
from .connection import QUICConnection
|
||||||
@ -442,7 +445,7 @@ class QUICListener(IListener):
|
|||||||
cert = server_config.certificate
|
cert = server_config.certificate
|
||||||
has_libp2p_ext = False
|
has_libp2p_ext = False
|
||||||
for ext in cert.extensions:
|
for ext in cert.extensions:
|
||||||
if str(ext.oid) == "1.3.6.1.4.1.53594.1.1":
|
if ext.oid == LIBP2P_TLS_EXTENSION_OID:
|
||||||
has_libp2p_ext = True
|
has_libp2p_ext = True
|
||||||
break
|
break
|
||||||
print(f"🔧 NEW_CONN: Certificate has libp2p extension: {has_libp2p_ext}")
|
print(f"🔧 NEW_CONN: Certificate has libp2p extension: {has_libp2p_ext}")
|
||||||
@ -557,10 +560,10 @@ class QUICListener(IListener):
|
|||||||
cert = config.certificate
|
cert = config.certificate
|
||||||
print(f"🔧 QUIC_STATE: Certificate subject: {cert.subject}")
|
print(f"🔧 QUIC_STATE: Certificate subject: {cert.subject}")
|
||||||
print(
|
print(
|
||||||
f"🔧 QUIC_STATE: Certificate valid from: {cert.not_valid_before}"
|
f"🔧 QUIC_STATE: Certificate valid from: {cert.not_valid_before_utc}"
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
f"🔧 QUIC_STATE: Certificate valid until: {cert.not_valid_after}"
|
f"🔧 QUIC_STATE: Certificate valid until: {cert.not_valid_after_utc}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check for connection errors
|
# Check for connection errors
|
||||||
|
|||||||
@ -5,7 +5,6 @@ Based on go-libp2p and js-libp2p security patterns.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import logging
|
import logging
|
||||||
import ssl
|
import ssl
|
||||||
from typing import List, Optional, Union
|
from typing import List, Optional, Union
|
||||||
@ -280,15 +279,15 @@ class CertificateGenerator:
|
|||||||
libp2p_private_key, cert_public_key_bytes
|
libp2p_private_key, cert_public_key_bytes
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set validity period using datetime objects (FIXED)
|
from datetime import datetime, timedelta, timezone
|
||||||
now = datetime.utcnow() # Use datetime instead of time.time()
|
|
||||||
not_before = now - timedelta(seconds=CERTIFICATE_NOT_BEFORE_BUFFER)
|
now = datetime.now(timezone.utc)
|
||||||
|
not_before = now - timedelta(minutes=1)
|
||||||
not_after = now + timedelta(days=validity_days)
|
not_after = now + timedelta(days=validity_days)
|
||||||
|
|
||||||
# Generate serial number
|
# Generate serial number
|
||||||
serial_number = int(now.timestamp()) # Convert datetime to timestamp
|
serial_number = int(now.timestamp())
|
||||||
|
|
||||||
# Build certificate with proper datetime objects
|
|
||||||
certificate = (
|
certificate = (
|
||||||
x509.CertificateBuilder()
|
x509.CertificateBuilder()
|
||||||
.subject_name(
|
.subject_name(
|
||||||
@ -537,9 +536,8 @@ class QUICTLSSecurityConfig:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
libp2p_oid = "1.3.6.1.4.1.53594.1.1"
|
|
||||||
for ext in self.certificate.extensions:
|
for ext in self.certificate.extensions:
|
||||||
if str(ext.oid) == libp2p_oid:
|
if ext.oid == LIBP2P_TLS_EXTENSION_OID:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -554,14 +552,13 @@ class QUICTLSSecurityConfig:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
now = datetime.utcnow()
|
now = datetime.now(timezone.utc)
|
||||||
return (
|
not_before = self.certificate.not_valid_before_utc
|
||||||
self.certificate.not_valid_before
|
not_after = self.certificate.not_valid_after_utc
|
||||||
<= now
|
|
||||||
<= self.certificate.not_valid_after
|
return not_before <= now <= not_after
|
||||||
)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -578,8 +575,8 @@ class QUICTLSSecurityConfig:
|
|||||||
"subject": str(self.certificate.subject),
|
"subject": str(self.certificate.subject),
|
||||||
"issuer": str(self.certificate.issuer),
|
"issuer": str(self.certificate.issuer),
|
||||||
"serial_number": self.certificate.serial_number,
|
"serial_number": self.certificate.serial_number,
|
||||||
"not_valid_before": self.certificate.not_valid_before,
|
"not_valid_before_utc": self.certificate.not_valid_before_utc,
|
||||||
"not_valid_after": self.certificate.not_valid_after,
|
"not_valid_after_utc": self.certificate.not_valid_after_utc,
|
||||||
"has_libp2p_extension": self.has_libp2p_extension(),
|
"has_libp2p_extension": self.has_libp2p_extension(),
|
||||||
"is_valid": self.is_certificate_valid(),
|
"is_valid": self.is_certificate_valid(),
|
||||||
"certificate_key_match": self.validate_certificate_key_match(),
|
"certificate_key_match": self.validate_certificate_key_match(),
|
||||||
@ -630,7 +627,7 @@ def create_server_tls_config(
|
|||||||
peer_id=peer_id,
|
peer_id=peer_id,
|
||||||
is_client_config=False,
|
is_client_config=False,
|
||||||
config_name="server",
|
config_name="server",
|
||||||
verify_mode=False, # Server doesn't verify client certs in libp2p
|
verify_mode=ssl.CERT_REQUIRED, # Server doesn't verify client certs in libp2p
|
||||||
check_hostname=False,
|
check_hostname=False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
@ -661,7 +658,7 @@ def create_client_tls_config(
|
|||||||
peer_id=peer_id,
|
peer_id=peer_id,
|
||||||
is_client_config=True,
|
is_client_config=True,
|
||||||
config_name="client",
|
config_name="client",
|
||||||
verify_mode=False, # Client doesn't verify server certs in libp2p
|
verify_mode=ssl.CERT_NONE, # Client doesn't verify server certs in libp2p
|
||||||
check_hostname=False,
|
check_hostname=False,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ Updated to include Module 5 security integration.
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from aioquic.quic.configuration import (
|
from aioquic.quic.configuration import (
|
||||||
@ -202,48 +203,20 @@ class QUICTransport(ITransport):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# Access attributes directly from QUICTLSSecurityConfig
|
||||||
# The security manager should return cryptography objects
|
config.certificate = tls_config.certificate
|
||||||
# not DER bytes, but if it returns DER bytes, we need to handle that
|
config.private_key = tls_config.private_key
|
||||||
certificate = tls_config.certificate
|
config.certificate_chain = tls_config.certificate_chain
|
||||||
private_key = tls_config.private_key
|
|
||||||
|
|
||||||
# Check if we received DER bytes and need
|
|
||||||
# to convert to cryptography objects
|
|
||||||
if isinstance(certificate, bytes):
|
|
||||||
from cryptography import x509
|
|
||||||
|
|
||||||
certificate = x509.load_der_x509_certificate(certificate)
|
|
||||||
|
|
||||||
if isinstance(private_key, bytes):
|
|
||||||
from cryptography.hazmat.primitives import serialization
|
|
||||||
|
|
||||||
private_key = serialization.load_der_private_key( # type: ignore
|
|
||||||
private_key, password=None
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set directly on the configuration object
|
|
||||||
config.certificate = certificate
|
|
||||||
config.private_key = private_key
|
|
||||||
|
|
||||||
# Handle certificate chain if provided
|
|
||||||
certificate_chain = tls_config.certificate_chain
|
|
||||||
# Convert DER bytes to cryptography objects if needed
|
|
||||||
chain_objects = []
|
|
||||||
for cert in certificate_chain:
|
|
||||||
if isinstance(cert, bytes):
|
|
||||||
from cryptography import x509
|
|
||||||
|
|
||||||
cert = x509.load_der_x509_certificate(cert)
|
|
||||||
chain_objects.append(cert)
|
|
||||||
config.certificate_chain = chain_objects
|
|
||||||
|
|
||||||
# Set ALPN protocols
|
|
||||||
config.alpn_protocols = tls_config.alpn_protocols
|
config.alpn_protocols = tls_config.alpn_protocols
|
||||||
|
|
||||||
# Set certificate verification mode
|
# Set verification mode (though libp2p typically doesn't verify)
|
||||||
config.verify_mode = tls_config.verify_mode
|
config.verify_mode = tls_config.verify_mode
|
||||||
|
|
||||||
|
if tls_config.is_client_config:
|
||||||
|
config.verify_mode = ssl.CERT_NONE
|
||||||
|
else:
|
||||||
|
config.verify_mode = ssl.CERT_REQUIRED
|
||||||
|
|
||||||
logger.debug("Successfully applied TLS configuration to QUIC config")
|
logger.debug("Successfully applied TLS configuration to QUIC config")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@ -6,6 +6,7 @@ Based on go-libp2p and js-libp2p QUIC implementations.
|
|||||||
|
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
|
import ssl
|
||||||
|
|
||||||
from aioquic.quic.configuration import QuicConfiguration
|
from aioquic.quic.configuration import QuicConfiguration
|
||||||
import multiaddr
|
import multiaddr
|
||||||
@ -302,6 +303,7 @@ def create_server_config_from_base(
|
|||||||
try:
|
try:
|
||||||
# Create new server configuration from scratch
|
# Create new server configuration from scratch
|
||||||
server_config = QuicConfiguration(is_client=False)
|
server_config = QuicConfiguration(is_client=False)
|
||||||
|
server_config.verify_mode = ssl.CERT_REQUIRED
|
||||||
|
|
||||||
# Copy basic configuration attributes (these are safe to copy)
|
# Copy basic configuration attributes (these are safe to copy)
|
||||||
copyable_attrs = [
|
copyable_attrs = [
|
||||||
@ -343,18 +345,14 @@ def create_server_config_from_base(
|
|||||||
server_tls_config = security_manager.create_server_config()
|
server_tls_config = security_manager.create_server_config()
|
||||||
|
|
||||||
# Override with security manager's TLS configuration
|
# Override with security manager's TLS configuration
|
||||||
if "certificate" in server_tls_config:
|
if server_tls_config.certificate:
|
||||||
server_config.certificate = server_tls_config["certificate"]
|
server_config.certificate = server_tls_config.certificate
|
||||||
if "private_key" in server_tls_config:
|
if server_tls_config.private_key:
|
||||||
server_config.private_key = server_tls_config["private_key"]
|
server_config.private_key = server_tls_config.private_key
|
||||||
if "certificate_chain" in server_tls_config:
|
if server_tls_config.certificate_chain:
|
||||||
# type: ignore
|
server_config.certificate_chain = server_tls_config.certificate_chain
|
||||||
server_config.certificate_chain = server_tls_config[ # type: ignore
|
if server_tls_config.alpn_protocols:
|
||||||
"certificate_chain" # type: ignore
|
server_config.alpn_protocols = server_tls_config.alpn_protocols
|
||||||
]
|
|
||||||
if "alpn_protocols" in server_tls_config:
|
|
||||||
# type: ignore
|
|
||||||
server_config.alpn_protocols = server_tls_config["alpn_protocols"] # type: ignore
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to apply security manager config: {e}")
|
logger.warning(f"Failed to apply security manager config: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user