montana/Русский/Гиппокамп/Архив/cognitive_signature.py

381 lines
14 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
cognitive_signature.py Когнитивные подписи Montana
Montana Protocol
Подписание мыслей и сообщений с domain separation
"""
import hashlib
import hmac
import secrets
from typing import Optional, Dict, Tuple
from datetime import datetime, timezone
from enum import Enum
# ═══════════════════════════════════════════════════════════════════════════
# DOMAIN SEPARATION
# ═══════════════════════════════════════════════════════════════════════════
class DomainType(Enum):
"""
Типы доменов для domain separation
Domain separation гарантирует что подпись для одного контекста
не может быть переиспользована в другом
"""
THOUGHT = "montana.thought" # Сырая мысль
MESSAGE = "montana.message" # Обычное сообщение
TRANSACTION = "montana.transaction" # Транзакция
PRESENCE = "montana.presence" # Proof of Presence
NODE_AUTH = "montana.node.auth" # Аутентификация узла
SYNC = "montana.sync" # Синхронизация данных
def get_domain_prefix(domain: DomainType) -> bytes:
"""
Получить префикс домена для domain separation
Args:
domain: Тип домена
Returns:
Префикс в байтах
Example:
>>> get_domain_prefix(DomainType.THOUGHT)
b'montana.thought'
"""
return domain.value.encode('utf-8')
# ═══════════════════════════════════════════════════════════════════════════
# COGNITIVE SIGNATURE
# ═══════════════════════════════════════════════════════════════════════════
class CognitiveSignature:
"""
Когнитивная подпись Montana
Использует HMAC-SHA256 с domain separation для подписания
мыслей, сообщений и других данных
"""
def __init__(self, secret_key: Optional[bytes] = None):
"""
Args:
secret_key: Секретный ключ (32 байта).
Если не указан, генерируется случайно.
"""
if secret_key is None:
self.secret_key = secrets.token_bytes(32)
else:
if len(secret_key) != 32:
raise ValueError("Secret key must be exactly 32 bytes")
self.secret_key = secret_key
def sign(
self,
message: str,
domain: DomainType,
timestamp: Optional[str] = None,
metadata: Optional[Dict] = None
) -> Dict:
"""
Подписать сообщение
Args:
message: Текст сообщения
domain: Домен для domain separation
timestamp: Timestamp в ISO format (UTC)
metadata: Дополнительные метаданные
Returns:
{
"message": "текст",
"domain": "montana.thought",
"timestamp": "2026-01-20T12:00:00+00:00",
"signature": "hex...",
"metadata": {}
}
"""
if timestamp is None:
timestamp = datetime.now(timezone.utc).isoformat()
# Собираем данные для подписи
domain_prefix = get_domain_prefix(domain)
message_bytes = message.encode('utf-8')
timestamp_bytes = timestamp.encode('utf-8')
# Формат: domain || timestamp || message
data_to_sign = domain_prefix + b'||' + timestamp_bytes + b'||' + message_bytes
# Подписываем с HMAC-SHA256
signature = hmac.new(
self.secret_key,
data_to_sign,
hashlib.sha256
).hexdigest()
return {
"message": message,
"domain": domain.value,
"timestamp": timestamp,
"signature": signature,
"metadata": metadata or {}
}
def verify(
self,
signed_data: Dict,
domain: Optional[DomainType] = None
) -> bool:
"""
Верифицировать подпись
Args:
signed_data: Подписанные данные (результат sign())
domain: Ожидаемый домен (опционально)
Returns:
True если подпись валидна
"""
try:
message = signed_data["message"]
domain_str = signed_data["domain"]
timestamp = signed_data["timestamp"]
signature = signed_data["signature"]
# Проверяем домен если указан
if domain:
if domain_str != domain.value:
return False
# Восстанавливаем domain enum
domain_enum = DomainType(domain_str)
# Пересобираем данные
domain_prefix = get_domain_prefix(domain_enum)
message_bytes = message.encode('utf-8')
timestamp_bytes = timestamp.encode('utf-8')
data_to_sign = domain_prefix + b'||' + timestamp_bytes + b'||' + message_bytes
# Вычисляем ожидаемую подпись
expected_signature = hmac.new(
self.secret_key,
data_to_sign,
hashlib.sha256
).hexdigest()
# Сравниваем
return hmac.compare_digest(signature, expected_signature)
except (KeyError, ValueError):
return False
def sign_thought(self, thought: str, user_id: Optional[int] = None) -> Dict:
"""
Подписать сырую мысль
Args:
thought: Текст мысли
user_id: ID пользователя
Returns:
Подписанная мысль
"""
metadata = {}
if user_id:
metadata["user_id"] = user_id
return self.sign(
message=thought,
domain=DomainType.THOUGHT,
metadata=metadata
)
def sign_message(self, message: str, sender_id: Optional[int] = None) -> Dict:
"""
Подписать обычное сообщение
Args:
message: Текст сообщения
sender_id: ID отправителя
Returns:
Подписанное сообщение
"""
metadata = {}
if sender_id:
metadata["sender_id"] = sender_id
return self.sign(
message=message,
domain=DomainType.MESSAGE,
metadata=metadata
)
def sign_transaction(
self,
transaction_data: str,
from_address: Optional[str] = None,
to_address: Optional[str] = None,
amount: Optional[float] = None
) -> Dict:
"""
Подписать транзакцию
Args:
transaction_data: Данные транзакции
from_address: Адрес отправителя
to_address: Адрес получателя
amount: Сумма
Returns:
Подписанная транзакция
"""
metadata = {}
if from_address:
metadata["from"] = from_address
if to_address:
metadata["to"] = to_address
if amount:
metadata["amount"] = amount
return self.sign(
message=transaction_data,
domain=DomainType.TRANSACTION,
metadata=metadata
)
def sign_presence(self, presence_data: str, user_id: Optional[int] = None) -> Dict:
"""
Подписать proof of presence
Args:
presence_data: Данные присутствия
user_id: ID пользователя
Returns:
Подписанное proof of presence
"""
metadata = {}
if user_id:
metadata["user_id"] = user_id
return self.sign(
message=presence_data,
domain=DomainType.PRESENCE,
metadata=metadata
)
# ═══════════════════════════════════════════════════════════════════════════
# KEY MANAGEMENT
# ═══════════════════════════════════════════════════════════════════════════
def generate_keypair() -> Tuple[bytes, bytes]:
"""
Сгенерировать пару ключей (secret, public)
В текущей реализации используется симметричный ключ (HMAC),
поэтому "публичный" ключ это хеш секретного ключа
Returns:
(secret_key, public_key_hash)
"""
secret_key = secrets.token_bytes(32)
# "Публичный" ключ — хеш секретного
public_key_hash = hashlib.sha256(secret_key).digest()
return (secret_key, public_key_hash)
def derive_key_from_passphrase(passphrase: str, salt: Optional[bytes] = None) -> bytes:
"""
Получить ключ из парольной фразы
Args:
passphrase: Парольная фраза
salt: Соль (16 байт, если не указана генерируется)
Returns:
32-байтовый ключ
"""
if salt is None:
salt = secrets.token_bytes(16)
# PBKDF2 с SHA256
key = hashlib.pbkdf2_hmac(
'sha256',
passphrase.encode('utf-8'),
salt,
100_000 # итераций
)
return key
# ═══════════════════════════════════════════════════════════════════════════
# EXPORTS
# ═══════════════════════════════════════════════════════════════════════════
__all__ = [
'DomainType',
'get_domain_prefix',
'CognitiveSignature',
'generate_keypair',
'derive_key_from_passphrase'
]
# ═══════════════════════════════════════════════════════════════════════════
# CLI
# ═══════════════════════════════════════════════════════════════════════════
if __name__ == "__main__":
print("🧠 Montana Cognitive Signature")
print("=" * 60)
# Генерируем ключ
print("\n🔑 Генерация ключей:")
secret_key, public_key_hash = generate_keypair()
print(f" Secret key (hex): {secret_key.hex()[:32]}...")
print(f" Public key hash (hex): {public_key_hash.hex()[:32]}...")
# Создаём signer
signer = CognitiveSignature(secret_key)
# Подписываем мысль
print("\n💭 Подписание мысли:")
thought = "Маска тяжелее лица"
signed_thought = signer.sign_thought(thought, user_id=123)
print(f" Мысль: {signed_thought['message']}")
print(f" Домен: {signed_thought['domain']}")
print(f" Timestamp: {signed_thought['timestamp']}")
print(f" Подпись: {signed_thought['signature'][:32]}...")
# Верификация
print("\n✅ Верификация:")
is_valid = signer.verify(signed_thought, domain=DomainType.THOUGHT)
print(f" Подпись валидна: {is_valid}")
# Подделка подписи
print("\n❌ Попытка подделки:")
forged = signed_thought.copy()
forged["message"] = "Поддельная мысль"
is_valid_forged = signer.verify(forged, domain=DomainType.THOUGHT)
print(f" Поддельная подпись валидна: {is_valid_forged}")
# Domain separation
print("\n🔒 Domain separation:")
print(" Пытаемся верифицировать мысль как сообщение...")
is_valid_wrong_domain = signer.verify(signed_thought, domain=DomainType.MESSAGE)
print(f" Подпись валидна в другом домене: {is_valid_wrong_domain}")
print("\n🎯 Когнитивные подписи готовы!")