Files
secpaste/providers/dpaste.py
nanoclaw ff41256f2f Initial commit: SecPaste encrypted pastebin client
SecPaste is a Python library and CLI tool for sharing encrypted content via
public pastebin services with zero-knowledge architecture.

Features:
- Pluggable crypto backends (AES-256-GCM, ChaCha20-Poly1305, Kyber-768)
- Pluggable pastebin providers (dpaste.com, extensible)
- URL fragment key storage (key never sent to server)
- Both CLI and library usage
- Post-quantum cryptography support (experimental)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-07 22:52:32 +00:00

104 lines
2.9 KiB
Python

"""dpaste.com provider implementation."""
import base64
import requests
from typing import Optional
from .base import PastebinProvider
class DPasteProvider(PastebinProvider):
"""Provider for dpaste.com pastebin service."""
BASE_URL = "https://dpaste.com"
def __init__(self, api_url: Optional[str] = None):
"""
Initialize dpaste provider.
Args:
api_url: Override API URL (useful for self-hosted instances)
"""
self.api_url = api_url or self.BASE_URL
def paste(self, content: bytes, expiry: str = "onetime", syntax: str = "text", **kwargs) -> str:
"""
Upload encrypted content to dpaste.
Args:
content: Encrypted bytes to upload
expiry: Expiration time (onetime, hour, day, week, month, never)
syntax: Syntax highlighting (text, python, etc.)
**kwargs: Additional provider-specific options
Returns:
Full paste URL (without fragment)
"""
# Base64 encode binary content for safe transmission
content_b64 = base64.b64encode(content).decode('ascii')
# dpaste API expects form data
data = {
'content': content_b64,
'syntax': syntax,
'expiry_days': self._convert_expiry(expiry),
}
# POST to create paste
response = requests.post(
f"{self.api_url}/api/v2/",
data=data,
headers={'User-Agent': 'SecPaste/0.1.0'}
)
response.raise_for_status()
# dpaste returns plain text URL
paste_url = response.text.strip()
return paste_url
def fetch(self, paste_id: str) -> bytes:
"""
Fetch encrypted content from dpaste.
Args:
paste_id: Full URL or just the paste ID
Returns:
Encrypted bytes (base64 decoded)
"""
# Handle both full URLs and just IDs
if paste_id.startswith('http'):
url = paste_id
else:
url = f"{self.api_url}/{paste_id}"
# Add .raw to get raw content
if not url.endswith('.raw'):
url = f"{url}.raw"
response = requests.get(url, headers={'User-Agent': 'SecPaste/0.1.0'})
response.raise_for_status()
# Decode from base64
content = base64.b64decode(response.text.strip())
return content
def get_name(self) -> str:
"""Return provider name."""
return "dpaste"
def get_base_url(self) -> str:
"""Return base URL."""
return self.api_url
def _convert_expiry(self, expiry: str) -> str:
"""Convert expiry string to dpaste format."""
expiry_map = {
'onetime': '0',
'hour': '1',
'day': '1',
'week': '7',
'month': '30',
'never': '365' # dpaste max is 365 days
}
return expiry_map.get(expiry, '7')