Python SDK Guide
Installation
bash
pip install requests cryptography
# or
pip3 install requests cryptographyBasic Usage
python
import requests
import hmac
import hashlib
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
import base64
API_BASE_URL = 'https://keyclaim.org/api'
API_KEY = 'kc_your_api_key_here'
# Step 1: Create a challenge
def create_challenge():
response = requests.post(
f'{API_BASE_URL}/challenge/create',
json={'key': API_KEY, 'ttl': 30}
)
response.raise_for_status()
return response.json()['challenge']
# Step 2: Generate response from challenge
# Option A: HMAC-based response (recommended for backend)
def generate_response_hmac(challenge, secret):
return hmac.new(
secret.encode('utf-8'),
challenge.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Option B: RSA Encryption-based (for frontend with private key)
def decrypt_challenge(encrypted_challenge, private_key_pem):
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
# Load private key
private_key = serialization.load_pem_private_key(
private_key_pem.encode('utf-8'),
password=None,
backend=default_backend()
)
# Decrypt
encrypted_bytes = base64.b64decode(encrypted_challenge)
decrypted = private_key.decrypt(
encrypted_bytes,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashlib.sha256()),
algorithm=hashlib.sha256(),
label=None
)
)
return decrypted.decode('utf-8')
# Step 3: Validate the response
def validate_challenge(challenge, response, decrypted_challenge=None):
payload = {
'key': API_KEY,
'challenge': challenge,
'response': response
}
if decrypted_challenge:
payload['decryptedChallenge'] = decrypted_challenge
response_obj = requests.post(
f'{API_BASE_URL}/challenge/validate',
json=payload
)
response_obj.raise_for_status()
return response_obj.json()
# Complete example (HMAC)
def main_hmac():
try:
# Create challenge
challenge = create_challenge()
print(f'Challenge: {challenge}')
# Generate response
secret = API_KEY
response = generate_response_hmac(challenge, secret)
print(f'Response: {response}')
# Validate
result = validate_challenge(challenge, response)
print(f'Validation result: {result}')
if result['valid']:
print('✓ Challenge validated successfully!')
if result.get('signature'):
print(f'Signature: {result["signature"]}')
else:
print('✗ Validation failed')
except Exception as error:
print(f'Error: {error}')
# Complete example (RSA Encryption)
def main_rsa(private_key_pem):
try:
# Create encrypted challenge
response_obj = requests.post(
f'{API_BASE_URL}/challenge/create',
json={'key': API_KEY, 'ttl': 30, 'encrypted': True}
)
response_obj.raise_for_status()
data = response_obj.json()
encrypted_challenge = data['challenge']
print(f'Encrypted Challenge: {encrypted_challenge}')
# Decrypt with private key
decrypted_challenge = decrypt_challenge(encrypted_challenge, private_key_pem)
print(f'Decrypted Challenge: {decrypted_challenge}')
# Validate (send decrypted challenge as response)
result = validate_challenge(
encrypted_challenge,
decrypted_challenge, # Response is the decrypted value
decrypted_challenge # Also send as decryptedChallenge
)
print(f'Validation result: {result}')
if result['valid']:
print('✓ Challenge validated successfully!')
except Exception as error:
print(f'Error: {error}')
if __name__ == '__main__':
# Use HMAC method
main_hmac()
# Or use RSA encryption method (if you have a private key)
# with open('private_key.pem', 'r') as f:
# private_key = f.read()
# main_rsa(private_key)Complete SDK Class
python
import requests
import hmac
import hashlib
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.backends import default_backend
import base64
class KeyClaimClient:
def __init__(self, api_key, base_url='https://keyclaim.org/api', private_key=None):
self.api_key = api_key
self.base_url = base_url
self.private_key_pem = private_key
def create_challenge(self, ttl=30):
"""Create a new challenge"""
response = requests.post(
f'{self.base_url}/challenge/create',
headers={'Authorization': f'Bearer {self.api_key}'},
json={'ttl': ttl}
)
response.raise_for_status()
return response.json()
def generate_response_hmac(self, challenge):
"""Generate HMAC-SHA256 response"""
return hmac.new(
self.api_key.encode('utf-8'),
challenge.encode('utf-8'),
hashlib.sha256
).hexdigest()
def decrypt_challenge(self, encrypted_challenge):
"""Decrypt challenge with private key"""
if not self.private_key_pem:
raise ValueError('Private key not provided')
private_key = serialization.load_pem_private_key(
self.private_key_pem.encode('utf-8'),
password=None,
backend=default_backend()
)
encrypted_bytes = base64.b64decode(encrypted_challenge)
decrypted = private_key.decrypt(
encrypted_bytes,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashlib.sha256()),
algorithm=hashlib.sha256(),
label=None
)
)
return decrypted.decode('utf-8')
def validate(self, challenge, response, decrypted_challenge=None):
"""Validate a challenge-response pair"""
payload = {
'key': self.api_key,
'challenge': challenge,
'response': response
}
if decrypted_challenge:
payload['decryptedChallenge'] = decrypted_challenge
response_obj = requests.post(
f'{self.base_url}/challenge/validate',
json=payload
)
response_obj.raise_for_status()
return response_obj.json()
def validate_challenge(self, challenge, method='hmac'):
"""Convenience method to validate a challenge"""
if method == 'hmac':
response = self.generate_response_hmac(challenge)
return self.validate(challenge, response)
elif method == 'rsa' and self.private_key_pem:
decrypted = self.decrypt_challenge(challenge)
return self.validate(challenge, decrypted, decrypted)
else:
raise ValueError(f'Unknown method: {method}')
# Usage
client = KeyClaimClient('kc_your_api_key', 'https://keyclaim.org/api')
# HMAC method
result = client.create_challenge()
challenge = result['challenge']
validation = client.validate_challenge(challenge, 'hmac')
print(validation)
# RSA method (with private key)
# client_rsa = KeyClaimClient('kc_your_api_key', private_key=open('private_key.pem').read())
# If API key has a key pair assigned, challenge will be automatically encrypted
# result = client_rsa.create_challenge()
# challenge = result['challenge']
# validation = client_rsa.validate_challenge(challenge, 'rsa')
# print(validation)Error Handling
python
import requests
def create_challenge_with_retry(max_retries=3):
for i in range(max_retries):
try:
response = requests.post(
f'{API_BASE_URL}/challenge/create',
json={'key': API_KEY, 'ttl': 30},
timeout=10
)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
raise ValueError('Invalid API key')
if e.response.status_code == 403:
raise ValueError('Rate limited or security check failed')
if i == max_retries - 1:
raise
time.sleep(1 * (i + 1))
except requests.exceptions.RequestException as e:
if i == max_retries - 1:
raise
time.sleep(1 * (i + 1))RSA Key Pair Generation
python
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
def generate_rsa_key_pair(key_size=2048):
"""Generate RSA key pair"""
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=key_size,
backend=default_backend()
)
# Get public key
public_key = private_key.public_key()
# Serialize private key
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
# Serialize public key
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
return {
'private_key': private_pem.decode('utf-8'),
'public_key': public_pem.decode('utf-8')
}
# Generate and save
key_pair = generate_rsa_key_pair(2048)
with open('private_key.pem', 'w') as f:
f.write(key_pair['private_key'])
with open('public_key.pem', 'w') as f:
f.write(key_pair['public_key'])
print('Key pair generated!')
print('Private key saved to: private_key.pem')
print('Public key saved to: public_key.pem')
print('\n⚠️ Keep your private key secure!')Explore Other Documentation
Choose your preferred programming language

Node.js Documentation
JavaScript/TypeScript integration guide
View Guide→

PHP Documentation
PHP 7.4+ integration guide
View Guide→

Java Documentation
Java 8+ integration guide
View Guide→

Kotlin Documentation
Kotlin/JVM integration guide
View Guide→
C# Documentation
.NET/C# integration guide
View Guide→

Go Documentation
Go 1.18+ integration guide
View Guide→
