Sign and Verify Message
Learn how to sign messages with a Solana keypair and verify message signatures for authentication and integrity verification.
Code Example
#!/usr/bin/env python3
"""
Solana Cookbook - How to Sign and Verify a Message
"""
from solders.keypair import Keypair
from solders.pubkey import Pubkey
import nacl.signing
import nacl.encoding
def main():
# Create a keypair
keypair = Keypair()
message = b"Hello, Solana!"
# Sign the message
signature = keypair.sign_message(message)
print(f"Message: {message}")
print(f"Signature: {signature}")
print(f"Public Key: {keypair.pubkey()}")
# Verify the signature
try:
# Use nacl to verify the signature
verify_key = nacl.signing.VerifyKey(keypair.pubkey().__bytes__())
verify_key.verify(message, signature.__bytes__())
print("Signature is valid: True")
except Exception as e:
print(f"Signature is valid: False - {e}")
if __name__ == "__main__":
main()
Explanation
This example demonstrates message signing and verification:
- Create Keypair: Generate a new keypair for signing
- Define Message: Create a message to sign (as bytes)
- Sign Message: Use
keypair.sign_message()
to create a signature - Verify Signature: Use NaCl library to verify the signature's authenticity
- Handle Verification: Catch exceptions if signature verification fails
Key Concepts
- Digital Signatures: Cryptographic proof that a message was signed by a specific private key
- Message Signing: Creating a signature that proves ownership of a private key
- Signature Verification: Confirming that a signature was created by the holder of a private key
- Ed25519 Signatures: Solana uses Ed25519 elliptic curve signatures
- Non-repudiation: Signed messages provide proof of authenticity
Usage
To run this example:
-
Install required dependencies:
pip install solders pynacl
-
Run the script:
python sign_verify_message.py
The output will show the message, signature, public key, and verification result.
Extended Examples
Sign and Verify with Different Keys
def demonstrate_signature_verification():
"""Demonstrate signature verification with different keypairs"""
# Create signer keypair
signer = Keypair()
message = b"This is a test message"
# Sign the message
signature = signer.sign_message(message)
# Verify with correct public key
try:
verify_key = nacl.signing.VerifyKey(signer.pubkey().__bytes__())
verify_key.verify(message, signature.__bytes__())
print("✓ Signature verified with correct public key")
except:
print("✗ Signature verification failed")
# Try to verify with wrong public key
wrong_keypair = Keypair()
try:
wrong_verify_key = nacl.signing.VerifyKey(wrong_keypair.pubkey().__bytes__())
wrong_verify_key.verify(message, signature.__bytes__())
print("✗ This should not happen - wrong key verified!")
except:
print("✓ Signature correctly rejected with wrong public key")
Message Authentication Function
def authenticate_message(message: bytes, signature: bytes, public_key: Pubkey) -> bool:
"""Authenticate a message with its signature and public key"""
try:
verify_key = nacl.signing.VerifyKey(public_key.__bytes__())
verify_key.verify(message, signature)
return True
except Exception:
return False
# Usage
keypair = Keypair()
message = b"Authenticate this message"
signature = keypair.sign_message(message)
is_authentic = authenticate_message(message, signature.__bytes__(), keypair.pubkey())
print(f"Message is authentic: {is_authentic}")
Batch Message Verification
def verify_multiple_messages(messages_and_signatures: list) -> dict:
"""Verify multiple message-signature pairs"""
results = {}
for i, (message, signature, public_key) in enumerate(messages_and_signatures):
try:
verify_key = nacl.signing.VerifyKey(public_key.__bytes__())
verify_key.verify(message, signature)
results[f"message_{i}"] = True
except Exception as e:
results[f"message_{i}"] = False
return results
Practical Applications
User Authentication
def authenticate_user(user_address: str, challenge: bytes, signature: bytes) -> bool:
"""Authenticate a user by verifying they signed a challenge"""
try:
public_key = Pubkey.from_string(user_address)
verify_key = nacl.signing.VerifyKey(public_key.__bytes__())
verify_key.verify(challenge, signature)
return True
except:
return False
Message Integrity
def create_signed_message(keypair: Keypair, message: str) -> dict:
"""Create a signed message with metadata"""
message_bytes = message.encode('utf-8')
signature = keypair.sign_message(message_bytes)
return {
"message": message,
"signature": signature.__bytes__().hex(),
"public_key": str(keypair.pubkey()),
"timestamp": int(time.time())
}
def verify_signed_message(signed_message: dict) -> bool:
"""Verify a signed message with metadata"""
try:
message_bytes = signed_message["message"].encode('utf-8')
signature = bytes.fromhex(signed_message["signature"])
public_key = Pubkey.from_string(signed_message["public_key"])
verify_key = nacl.signing.VerifyKey(public_key.__bytes__())
verify_key.verify(message_bytes, signature)
return True
except:
return False
Security Considerations
- Message Format: Always use bytes for message signing
- Signature Storage: Store signatures securely and never reuse them
- Public Key Validation: Always validate public keys before verification
- Replay Protection: Include timestamps or nonces in messages
- Error Handling: Properly handle verification failures
Common Use Cases
- Wallet Authentication: Prove ownership of a wallet address
- Message Integrity: Ensure messages haven't been tampered with
- API Authentication: Authenticate API requests with signatures
- Decentralized Identity: Create cryptographic proof of identity
- Smart Contract Interactions: Sign off-chain messages for on-chain verification
Error Handling
def safe_sign_and_verify(keypair: Keypair, message: bytes) -> tuple:
"""Safely sign and verify a message with error handling"""
try:
signature = keypair.sign_message(message)
verify_key = nacl.signing.VerifyKey(keypair.pubkey().__bytes__())
verify_key.verify(message, signature.__bytes__())
return True, signature
except Exception as e:
return False, f"Error: {e}"
Note: Message signing is different from transaction signing - it's used for authentication and integrity verification rather than blockchain transactions.