mirror of
https://github.com/luxfi/corona.git
synced 2026-09-24 00:25:54 +00:00
audit 2026-06: TEE + GPU + public-permissionless-chain safety + corona->corona sweep
AUDIT-2026-06.md ships the four-dimensional audit:
D1 Permissionless safety: PASSED with two minor open items for v0.7.6.
Rogue-key NOT APPLICABLE (single global (A, bTilde); no per-party pk
in the BLS-aggregation sense). Adaptive corruption documented as
paper-cited only (carryover; GATE-4 target). Slashable equivocation
evidence is cryptographically extractable via signed dkg2.Complaint
and activation-cert non-verification. Front-running: sid IS bound
into PRNG seed / MAC / transcript hash (CRIT-1 fix 2026-05-03), but
plumbed as Go int (64-bit), not 32-byte randomness as threat-model
claims — D1-2 MEDIUM, doc tightening for v0.7.6. D1-3 MINOR: extend
Complaint to signing-round equivocation.
D2 TEE integration: WAS A GAP. Closed by this audit via the new
docs/mptc/tee-integration.md — full per-platform spec for AMD
SEV-SNP (primary Linux path), NVIDIA Confidential Computing
(H100/H200/B200 CC mode) when gpu.UseAccelerator() is used in
production, Intel TDX (alternative), Apple Secure Enclave (local-
only defense-in-depth on Apple Silicon). Intel SGX explicitly NOT
RECOMMENDED. Decomplecting rule held: ZERO Corona kernel code
change required for §3.1, §3.3, §3.4; §3.2 adds one optional
plumbing function (gpu.MaybeRegisterAttested) tracked for v0.7.6.
The TEE layer sits OUTSIDE the cryptographic math — Corona observes
nothing of TEE state.
D3 GPU acceleration inventory: corona/gpu is a thin SubRing-registration
shim around luxfi/lattice/v7/gpu — no kernels live in corona/.
dkg2_parallel.go is goroutine fan-out (honestly relabelled in
ca3389c), not GPU dispatch. Sister-repo lux-private/gpu-kernels/
ops/mpcvm/*/mpcvm_corona.* and ops/crypto/corona/ carry the
legacy name — D3-1 INFORMATIONAL, cross-repo rename TODO.
D4 corona->corona sweep (in-repo COMPLETE):
* Makefile: BINARY_NAME corona -> corona; banner + docker tag.
* Dockerfile: addgroup/adduser/binary-path/entrypoint.
* .github/workflows/ci.yml: bin/corona -> bin/corona; artifact
name corona-${runner.os}-${arch}; release output name pattern.
* .golangci.yml: local-prefixes: corona -> github.com/luxfi/corona.
* docs/{app,content,lib,out,public,.source,mdx-components.tsx,...}
DROPPED — a fumadocs Next.js site (3057 lines) that framed Corona
as a privacy ring-signature scheme (Schnorr + linkability +
hash-to-curve + "ring signatures for transaction privacy"). That
is NOT Corona — Corona is a 2-round R-LWE threshold sig (Boschini
et al. 2024/1113). The site referenced a non-existent
github.com/luxfi/corona Go module. Removed.
* KEPT: docs/mptc/ (authoritative submission docs).
* KEPT: historical refs in CHANGELOG.md, LLM.md, and
CRYPTOGRAPHER-SIGN-OFF.md — they document the prior v0.4.x purge
and are correct as historical context.
* Cross-repo (luxfi/threshold, lux-private/gpu-kernels, luxfi/node)
inventoried as D4-1 INFORMATIONAL — sister-repo work items.
Build clean (GOWORK=off go build ./...). gofmt -s clean. vet clean.
Full short test suite green: dkg, dkg2, gpu, hash, keyera, networking,
primitives, reshare, sign, threshold, utils, wire — ALL ok.
KATs unchanged: no Go code paths edited; FIPS-TRACEABILITY byte-
equality contract preserved. v1.x ABI unchanged: no public Go API
modified. Constant-time discipline preserved: no crypto/subtle paths
touched; CONSTANT-TIME-REVIEW.md remains authoritative.
Production deployment posture (unchanged from v0.7.5): APPROVED WITH
ROADMAP GATES for public-permissionless deployment as a R-LWE
threshold signature primitive in Lux Quasar consensus, with v0.8.0
GATE-3b (10^9-sample dudect on pinned CPU) + GATE-4 (external audit)
+ GATE-5 (Jasmin extraction byte-walk) as carryover roadmap items.
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
.pnpm-store/
|
||||
|
||||
# Next.js
|
||||
.next/
|
||||
out/
|
||||
.turbo/
|
||||
|
||||
# Build
|
||||
dist/
|
||||
build/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Fumadocs
|
||||
.source/
|
||||
|
||||
# TypeScript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -1,42 +0,0 @@
|
||||
import { source } from "@/lib/source"
|
||||
import type { Metadata } from "next"
|
||||
import { DocsPage, DocsBody, DocsTitle, DocsDescription } from "fumadocs-ui/page"
|
||||
import { notFound } from "next/navigation"
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx"
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>
|
||||
}) {
|
||||
const params = await props.params
|
||||
const page = source.getPage(params.slug)
|
||||
if (!page) notFound()
|
||||
|
||||
const MDX = page.data.body
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDX components={{ ...defaultMdxComponents }} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
)
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return source.generateParams()
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
params: Promise<{ slug?: string[] }>
|
||||
}): Promise<Metadata> {
|
||||
const params = await props.params
|
||||
const page = source.getPage(params.slug)
|
||||
if (!page) notFound()
|
||||
|
||||
return {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { source } from "@/lib/source"
|
||||
import type { ReactNode } from "react"
|
||||
import { DocsLayout } from "fumadocs-ui/layouts/docs"
|
||||
|
||||
export default async function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<DocsLayout tree={source.pageTree} sidebar={{ defaultOpenLevel: 0 }}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
)
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
@import "tailwindcss";
|
||||
@import "fumadocs-ui/style.css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme inline {
|
||||
--breakpoint-3xl: 1600px;
|
||||
--breakpoint-4xl: 2000px;
|
||||
--font-sans: var(--font-geist-sans), system-ui, sans-serif;
|
||||
--font-mono: var(--font-geist-mono), monospace;
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import "./global.css"
|
||||
import { RootProvider } from "fumadocs-ui/provider/next"
|
||||
import { Inter } from "next/font/google"
|
||||
import type { ReactNode } from "react"
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-geist-sans",
|
||||
display: "swap",
|
||||
})
|
||||
|
||||
const interMono = Inter({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-geist-mono",
|
||||
display: "swap",
|
||||
})
|
||||
|
||||
export const metadata = {
|
||||
title: {
|
||||
default: "Corona Signatures Documentation",
|
||||
template: "%s | Corona Signatures",
|
||||
},
|
||||
description: "Ring signature implementation for privacy",
|
||||
}
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
className={`${inter.variable} ${interMono.variable}`}
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<body className="min-h-svh bg-background font-sans antialiased">
|
||||
<RootProvider
|
||||
search={{
|
||||
enabled: true,
|
||||
}}
|
||||
theme={{
|
||||
enabled: true,
|
||||
defaultTheme: "dark",
|
||||
}}
|
||||
>
|
||||
<div className="relative flex min-h-svh flex-col bg-background">
|
||||
{children}
|
||||
</div>
|
||||
</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import Link from "next/link"
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<main className="flex flex-1 flex-col items-center justify-center px-4">
|
||||
<div className="container flex flex-col items-center gap-12 py-24 sm:gap-16 sm:py-32">
|
||||
<div className="flex flex-col items-center gap-4 text-center">
|
||||
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl">
|
||||
Documentation
|
||||
</h1>
|
||||
<p className="max-w-2xl text-lg text-muted-foreground">
|
||||
Get started with our comprehensive documentation
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Link
|
||||
href="/docs"
|
||||
className="inline-flex h-10 items-center justify-center rounded-md bg-primary px-8 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90"
|
||||
>
|
||||
Get Started
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -1,644 +0,0 @@
|
||||
---
|
||||
title: API Reference
|
||||
description: Complete API documentation for Corona's cryptographic functions
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
## Core Types
|
||||
|
||||
### PublicKey
|
||||
|
||||
Represents an elliptic curve public key.
|
||||
|
||||
```go
|
||||
type PublicKey struct {
|
||||
X, Y *big.Int
|
||||
}
|
||||
|
||||
// Methods
|
||||
func (pk *PublicKey) Bytes() []byte
|
||||
func (pk *PublicKey) String() string
|
||||
func (pk *PublicKey) Equal(other *PublicKey) bool
|
||||
func (pk *PublicKey) Marshal() ([]byte, error)
|
||||
func (pk *PublicKey) Unmarshal(data []byte) error
|
||||
```
|
||||
|
||||
### PrivateKey
|
||||
|
||||
Represents an elliptic curve private key.
|
||||
|
||||
```go
|
||||
type PrivateKey big.Int
|
||||
|
||||
// Methods
|
||||
func (sk *PrivateKey) PublicKey() *PublicKey
|
||||
func (sk *PrivateKey) Bytes() []byte
|
||||
func (sk *PrivateKey) Clear()
|
||||
func (sk *PrivateKey) Sign(message []byte) (*Signature, error)
|
||||
```
|
||||
|
||||
### RingSignature
|
||||
|
||||
Complete ring signature with linkability.
|
||||
|
||||
```go
|
||||
type RingSignature struct {
|
||||
C0 *big.Int // Initial challenge
|
||||
S []*big.Int // Response values
|
||||
KeyImage *KeyImage // Linkability tag
|
||||
RingPubKeys []*PublicKey // Ring members
|
||||
}
|
||||
|
||||
// Methods
|
||||
func (rs *RingSignature) Serialize() []byte
|
||||
func (rs *RingSignature) Deserialize(data []byte) error
|
||||
func (rs *RingSignature) Size() int
|
||||
func (rs *RingSignature) IsValid() bool
|
||||
```
|
||||
|
||||
### KeyImage
|
||||
|
||||
Unique identifier for linkable signatures.
|
||||
|
||||
```go
|
||||
type KeyImage struct {
|
||||
X, Y *big.Int
|
||||
}
|
||||
|
||||
// Methods
|
||||
func (ki *KeyImage) Bytes() []byte
|
||||
func (ki *KeyImage) Equal(other *KeyImage) bool
|
||||
func (ki *KeyImage) String() string
|
||||
```
|
||||
|
||||
## Key Management
|
||||
|
||||
### GenerateKeyPair
|
||||
|
||||
Generate a new public/private key pair.
|
||||
|
||||
```go
|
||||
func GenerateKeyPair() (*PublicKey, *PrivateKey, error)
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
- `*PublicKey`: The generated public key
|
||||
- `*PrivateKey`: The generated private key
|
||||
- `error`: Any error that occurred
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
pub, priv, err := corona.GenerateKeyPair()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer priv.Clear() // Clean up private key
|
||||
```
|
||||
|
||||
### DerivePublicKey
|
||||
|
||||
Derive public key from private key.
|
||||
|
||||
```go
|
||||
func DerivePublicKey(privKey *PrivateKey) *PublicKey
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `privKey`: The private key to derive from
|
||||
|
||||
**Returns:**
|
||||
- `*PublicKey`: The corresponding public key
|
||||
|
||||
### GenerateKeyImage
|
||||
|
||||
Generate key image for linkability.
|
||||
|
||||
```go
|
||||
func GenerateKeyImage(privKey *PrivateKey) *KeyImage
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `privKey`: The private key for key image generation
|
||||
|
||||
**Returns:**
|
||||
- `*KeyImage`: The generated key image
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
keyImage := GenerateKeyImage(privKey)
|
||||
// Same private key always produces same key image
|
||||
```
|
||||
|
||||
## Ring Signature Functions
|
||||
|
||||
### SignRing
|
||||
|
||||
Create a ring signature for a message.
|
||||
|
||||
```go
|
||||
func SignRing(
|
||||
message []byte,
|
||||
ring []*PublicKey,
|
||||
signerIndex int,
|
||||
privKey *PrivateKey,
|
||||
) (*RingSignature, error)
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `message`: The message to sign
|
||||
- `ring`: Array of public keys forming the ring
|
||||
- `signerIndex`: Position of actual signer in ring (0-indexed)
|
||||
- `privKey`: Private key of the actual signer
|
||||
|
||||
**Returns:**
|
||||
- `*RingSignature`: The generated ring signature
|
||||
- `error`: Any error that occurred
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
ring := []*PublicKey{pk1, pk2, pk3, pk4}
|
||||
sig, err := SignRing(
|
||||
[]byte("transaction data"),
|
||||
ring,
|
||||
2, // signer is at index 2
|
||||
privKey3,
|
||||
)
|
||||
```
|
||||
|
||||
### VerifyRing
|
||||
|
||||
Verify a ring signature.
|
||||
|
||||
```go
|
||||
func VerifyRing(
|
||||
message []byte,
|
||||
signature *RingSignature,
|
||||
) bool
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `message`: The original message
|
||||
- `signature`: The ring signature to verify
|
||||
|
||||
**Returns:**
|
||||
- `bool`: True if signature is valid, false otherwise
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
valid := VerifyRing(message, signature)
|
||||
if !valid {
|
||||
return errors.New("invalid signature")
|
||||
}
|
||||
```
|
||||
|
||||
### CheckLinkability
|
||||
|
||||
Check if two signatures are linked (same signer).
|
||||
|
||||
```go
|
||||
func CheckLinkability(
|
||||
sig1 *RingSignature,
|
||||
sig2 *RingSignature,
|
||||
) bool
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `sig1`: First ring signature
|
||||
- `sig2`: Second ring signature
|
||||
|
||||
**Returns:**
|
||||
- `bool`: True if signatures are from the same private key
|
||||
|
||||
## Threshold Signatures
|
||||
|
||||
### Party
|
||||
|
||||
Represents a participant in threshold signing.
|
||||
|
||||
```go
|
||||
type Party struct {
|
||||
ID int
|
||||
Ring *ring.Ring
|
||||
RingXi *ring.Ring
|
||||
RingNu *ring.Ring
|
||||
UniformSampler *ring.UniformSampler
|
||||
SkShare structs.Vector[ring.Poly]
|
||||
// ... additional fields
|
||||
}
|
||||
|
||||
// Constructor
|
||||
func NewParty(
|
||||
id int,
|
||||
r *ring.Ring,
|
||||
r_xi *ring.Ring,
|
||||
r_nu *ring.Ring,
|
||||
sampler *ring.UniformSampler,
|
||||
) *Party
|
||||
```
|
||||
|
||||
### ThresholdSetup
|
||||
|
||||
Initialize threshold signature scheme.
|
||||
|
||||
```go
|
||||
func ThresholdSetup(
|
||||
n int, // Total parties
|
||||
t int, // Threshold
|
||||
secLevel int, // Security level
|
||||
) (*ThresholdConfig, error)
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `n`: Total number of parties
|
||||
- `t`: Minimum parties needed to sign
|
||||
- `secLevel`: Security level in bits (128, 192, 256)
|
||||
|
||||
**Returns:**
|
||||
- `*ThresholdConfig`: Configuration for threshold signing
|
||||
- `error`: Any error that occurred
|
||||
|
||||
### DistributedKeyGen
|
||||
|
||||
Generate distributed key shares.
|
||||
|
||||
```go
|
||||
func DistributedKeyGen(
|
||||
config *ThresholdConfig,
|
||||
parties []*Party,
|
||||
) (*PublicKey, map[int]*KeyShare, error)
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `config`: Threshold configuration
|
||||
- `parties`: Array of participating parties
|
||||
|
||||
**Returns:**
|
||||
- `*PublicKey`: The group public key
|
||||
- `map[int]*KeyShare`: Map of party ID to key share
|
||||
- `error`: Any error that occurred
|
||||
|
||||
### ThresholdSign
|
||||
|
||||
Perform threshold signing with t-of-n parties.
|
||||
|
||||
```go
|
||||
func ThresholdSign(
|
||||
message []byte,
|
||||
signers []*Party,
|
||||
threshold int,
|
||||
) (*ThresholdSignature, error)
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `message`: Message to sign
|
||||
- `signers`: Participating signers (must be >= threshold)
|
||||
- `threshold`: Minimum signers required
|
||||
|
||||
**Returns:**
|
||||
- `*ThresholdSignature`: The threshold signature
|
||||
- `error`: Any error that occurred
|
||||
|
||||
## Lattice Operations
|
||||
|
||||
### Polynomial Ring Functions
|
||||
|
||||
```go
|
||||
// Create new polynomial ring
|
||||
func NewRing(n int, q *big.Int) *ring.Ring
|
||||
|
||||
// Sample random polynomial
|
||||
func SamplePoly(r *ring.Ring) ring.Poly
|
||||
|
||||
// Polynomial multiplication
|
||||
func PolyMul(
|
||||
r *ring.Ring,
|
||||
a, b ring.Poly,
|
||||
) ring.Poly
|
||||
|
||||
// NTT transformation
|
||||
func NTT(r *ring.Ring, poly ring.Poly) ring.Poly
|
||||
|
||||
// Inverse NTT
|
||||
func INTT(r *ring.Ring, poly ring.Poly) ring.Poly
|
||||
```
|
||||
|
||||
### Matrix Operations
|
||||
|
||||
```go
|
||||
// Matrix-vector multiplication
|
||||
func MatrixVectorMul(
|
||||
r *ring.Ring,
|
||||
M structs.Matrix[ring.Poly],
|
||||
v structs.Vector[ring.Poly],
|
||||
) structs.Vector[ring.Poly]
|
||||
|
||||
// Matrix addition
|
||||
func MatrixAdd(
|
||||
r *ring.Ring,
|
||||
A, B structs.Matrix[ring.Poly],
|
||||
) structs.Matrix[ring.Poly]
|
||||
|
||||
// Sample random matrix
|
||||
func SamplePolyMatrix(
|
||||
r *ring.Ring,
|
||||
rows, cols int,
|
||||
sampler Sampler,
|
||||
) structs.Matrix[ring.Poly]
|
||||
```
|
||||
|
||||
## Utility Functions
|
||||
|
||||
### Hash Functions
|
||||
|
||||
```go
|
||||
// Hash to elliptic curve point
|
||||
func HashToPoint(data []byte) *Point
|
||||
|
||||
// Generate challenge hash
|
||||
func ChallengeHash(components ...[]byte) *big.Int
|
||||
|
||||
// SHA-256 hash
|
||||
func Hash256(data []byte) []byte
|
||||
|
||||
// Keccak-256 hash
|
||||
func Keccak256(data []byte) []byte
|
||||
```
|
||||
|
||||
### Serialization
|
||||
|
||||
```go
|
||||
// Serialize ring signature
|
||||
func SerializeRingSignature(sig *RingSignature) []byte
|
||||
|
||||
// Deserialize ring signature
|
||||
func DeserializeRingSignature(data []byte) (*RingSignature, error)
|
||||
|
||||
// Encode to base64
|
||||
func EncodeBase64(data []byte) string
|
||||
|
||||
// Decode from base64
|
||||
func DecodeBase64(s string) ([]byte, error)
|
||||
```
|
||||
|
||||
### Random Generation
|
||||
|
||||
```go
|
||||
// Generate secure random bytes
|
||||
func GenerateRandom(size int) ([]byte, error)
|
||||
|
||||
// Generate random scalar
|
||||
func RandomScalar() (*big.Int, error)
|
||||
|
||||
// Generate random point
|
||||
func RandomPoint() (*Point, error)
|
||||
|
||||
// Deterministic random from seed
|
||||
func DeterministicRandom(seed []byte, size int) []byte
|
||||
```
|
||||
|
||||
## Network Protocol
|
||||
|
||||
### Message Types
|
||||
|
||||
```go
|
||||
const (
|
||||
MsgKeyGenInit MessageType = 0x01
|
||||
MsgKeyGenShare MessageType = 0x02
|
||||
MsgSignRound1 MessageType = 0x10
|
||||
MsgSignRound2 MessageType = 0x11
|
||||
MsgSignRound3 MessageType = 0x12
|
||||
MsgAbort MessageType = 0xFF
|
||||
)
|
||||
```
|
||||
|
||||
### Network Functions
|
||||
|
||||
```go
|
||||
// Send message to party
|
||||
func SendMessage(
|
||||
party int,
|
||||
msg NetworkMessage,
|
||||
) error
|
||||
|
||||
// Broadcast to all parties
|
||||
func Broadcast(
|
||||
msg NetworkMessage,
|
||||
) error
|
||||
|
||||
// Receive messages
|
||||
func ReceiveMessages(
|
||||
expectedType MessageType,
|
||||
timeout time.Duration,
|
||||
) ([]NetworkMessage, error)
|
||||
|
||||
// Establish secure channel
|
||||
func EstablishChannel(
|
||||
partyID int,
|
||||
publicKey *PublicKey,
|
||||
) (*SecureChannel, error)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Config Structure
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// Ring signature parameters
|
||||
RingSize int
|
||||
Algorithm Algorithm
|
||||
HashFunction hash.Hash
|
||||
|
||||
// Lattice parameters
|
||||
PolyDegree int
|
||||
Modulus *big.Int
|
||||
ErrorStdDev float64
|
||||
|
||||
// Threshold parameters
|
||||
TotalParties int
|
||||
Threshold int
|
||||
|
||||
// Security
|
||||
SecurityLevel int
|
||||
QuantumSafe bool
|
||||
|
||||
// Performance
|
||||
ParallelOps bool
|
||||
CacheSize int
|
||||
}
|
||||
```
|
||||
|
||||
### Default Configurations
|
||||
|
||||
```go
|
||||
// Default configuration
|
||||
func DefaultConfig() *Config
|
||||
|
||||
// High security configuration
|
||||
func HighSecurityConfig() *Config
|
||||
|
||||
// Performance optimized configuration
|
||||
func PerformanceConfig() *Config
|
||||
|
||||
// Quantum-safe configuration
|
||||
func QuantumSafeConfig() *Config
|
||||
```
|
||||
|
||||
## Error Types
|
||||
|
||||
```go
|
||||
var (
|
||||
// Key errors
|
||||
ErrInvalidPrivateKey = errors.New("invalid private key")
|
||||
ErrInvalidPublicKey = errors.New("invalid public key")
|
||||
ErrKeyMismatch = errors.New("key mismatch")
|
||||
|
||||
// Signature errors
|
||||
ErrInvalidSignature = errors.New("invalid signature")
|
||||
ErrInvalidRingSize = errors.New("invalid ring size")
|
||||
ErrSignerNotInRing = errors.New("signer not in ring")
|
||||
|
||||
// Threshold errors
|
||||
ErrInsufficientSigners = errors.New("insufficient signers")
|
||||
ErrInvalidThreshold = errors.New("invalid threshold")
|
||||
ErrDuplicateSigner = errors.New("duplicate signer")
|
||||
|
||||
// Protocol errors
|
||||
ErrProtocolAborted = errors.New("protocol aborted")
|
||||
ErrTimeout = errors.New("operation timeout")
|
||||
ErrInvalidMAC = errors.New("invalid MAC")
|
||||
|
||||
// Lattice errors
|
||||
ErrInvalidPolynomial = errors.New("invalid polynomial")
|
||||
ErrNTTFailed = errors.New("NTT operation failed")
|
||||
)
|
||||
```
|
||||
|
||||
## Constants
|
||||
|
||||
```go
|
||||
const (
|
||||
// Default values
|
||||
DefaultRingSize = 16
|
||||
DefaultPolyDegree = 4096
|
||||
DefaultSecurityLevel = 128
|
||||
|
||||
// Size constants
|
||||
PublicKeySize = 64 // bytes
|
||||
PrivateKeySize = 32 // bytes
|
||||
KeyImageSize = 64 // bytes
|
||||
SignatureBase = 96 // bytes (before ring members)
|
||||
|
||||
// Algorithm identifiers
|
||||
AlgoSchnorr Algorithm = 0x01
|
||||
AlgoLattice Algorithm = 0x02
|
||||
AlgoHybrid Algorithm = 0x03
|
||||
|
||||
// Security levels
|
||||
SecurityLow = 80
|
||||
SecurityMedium = 128
|
||||
SecurityHigh = 192
|
||||
SecurityMax = 256
|
||||
)
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Basic Ring Signature
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/luxfi/corona"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Generate keys for ring members
|
||||
keys := make([]*corona.PublicKey, 16)
|
||||
var signerKey *corona.PrivateKey
|
||||
signerIndex := 7
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
pub, priv, err := corona.GenerateKeyPair()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
keys[i] = pub
|
||||
if i == signerIndex {
|
||||
signerKey = priv
|
||||
} else {
|
||||
priv.Clear() // Clean up other private keys
|
||||
}
|
||||
}
|
||||
|
||||
// Create and verify signature
|
||||
message := []byte("confidential transaction")
|
||||
|
||||
sig, err := corona.SignRing(
|
||||
message,
|
||||
keys,
|
||||
signerIndex,
|
||||
signerKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
valid := corona.VerifyRing(message, sig)
|
||||
fmt.Printf("Signature valid: %v\n", valid)
|
||||
|
||||
// Check linkability
|
||||
sig2, _ := corona.SignRing(
|
||||
[]byte("another message"),
|
||||
keys,
|
||||
signerIndex,
|
||||
signerKey,
|
||||
)
|
||||
|
||||
linked := corona.CheckLinkability(sig, sig2)
|
||||
fmt.Printf("Signatures linked: %v\n", linked)
|
||||
}
|
||||
```
|
||||
|
||||
### Threshold Signature
|
||||
|
||||
```go
|
||||
// Setup threshold scheme (3-of-5)
|
||||
config, err := corona.ThresholdSetup(5, 3, 128)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Initialize parties
|
||||
parties := make([]*corona.Party, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
parties[i] = corona.NewParty(i, config)
|
||||
}
|
||||
|
||||
// Generate distributed key
|
||||
pubKey, shares, err := corona.DistributedKeyGen(config, parties)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Sign with subset of parties (3 out of 5)
|
||||
signers := []*corona.Party{parties[0], parties[2], parties[4]}
|
||||
sig, err := corona.ThresholdSign(
|
||||
[]byte("message"),
|
||||
signers,
|
||||
3,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify threshold signature
|
||||
valid := corona.VerifyThreshold([]byte("message"), sig, pubKey)
|
||||
fmt.Printf("Threshold signature valid: %v\n", valid)
|
||||
```
|
||||
@@ -1,702 +0,0 @@
|
||||
---
|
||||
title: Implementation Guide
|
||||
description: Detailed implementation architecture and code structure of Corona
|
||||
---
|
||||
|
||||
# Implementation Guide
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
Corona is structured as a modular cryptographic library with clear separation of concerns:
|
||||
|
||||
```
|
||||
corona/
|
||||
├── primitives/ # Core cryptographic primitives
|
||||
├── sign/ # Signature generation and verification
|
||||
├── utils/ # Utility functions and helpers
|
||||
├── networking/ # Network communication layer
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### Primitives Package
|
||||
|
||||
The `primitives` package provides fundamental cryptographic operations:
|
||||
|
||||
```go
|
||||
// primitives/shamir.go
|
||||
package primitives
|
||||
|
||||
import (
|
||||
"github.com/luxfi/lattice/v6/ring"
|
||||
"github.com/luxfi/lattice/v6/utils/structs"
|
||||
)
|
||||
|
||||
// ShamirSecretSharing implements (t,n) threshold secret sharing
|
||||
func ShamirSecretSharing(
|
||||
r *ring.Ring,
|
||||
secret structs.Vector[ring.Poly],
|
||||
threshold int,
|
||||
lagrangeCoeffs structs.Vector[ring.Poly],
|
||||
) map[int]structs.Vector[ring.Poly] {
|
||||
// Generate random polynomial of degree threshold-1
|
||||
// Evaluate at n points to create shares
|
||||
// Return map of party ID to share
|
||||
}
|
||||
```
|
||||
|
||||
#### Hash Functions
|
||||
|
||||
Secure hash operations for ring signatures:
|
||||
|
||||
```go
|
||||
// primitives/hash.go
|
||||
func HashToPoint(data []byte) *Point {
|
||||
// Hash arbitrary data to elliptic curve point
|
||||
// Used for key image generation
|
||||
h := sha256.Sum256(data)
|
||||
// Map hash to curve point deterministically
|
||||
return mapToCurve(h[:])
|
||||
}
|
||||
|
||||
func ChallengeHash(components ...[]byte) *big.Int {
|
||||
// Generate challenge for ring signature
|
||||
h := sha256.New()
|
||||
for _, c := range components {
|
||||
h.Write(c)
|
||||
}
|
||||
return new(big.Int).SetBytes(h.Sum(nil))
|
||||
}
|
||||
```
|
||||
|
||||
### Signature Package
|
||||
|
||||
The `sign` package implements the ring signature protocol:
|
||||
|
||||
```go
|
||||
// sign/sign.go
|
||||
package sign
|
||||
|
||||
type Party struct {
|
||||
ID int
|
||||
Ring *ring.Ring // Polynomial ring
|
||||
RingXi *ring.Ring // Rounding ring
|
||||
RingNu *ring.Ring // Verification ring
|
||||
UniformSampler *ring.UniformSampler
|
||||
SkShare structs.Vector[ring.Poly] // Secret key share
|
||||
Seed map[int][][]byte // PRG seeds
|
||||
R structs.Matrix[ring.Poly]
|
||||
C ring.Poly // Challenge
|
||||
H structs.Vector[ring.Poly]
|
||||
Lambda ring.Poly // Lagrange coefficient
|
||||
D structs.Matrix[ring.Poly]
|
||||
MACKeys map[int][]byte // MAC keys for parties
|
||||
MACs map[int][]byte // Message auth codes
|
||||
}
|
||||
```
|
||||
|
||||
#### Signature Generation Phases
|
||||
|
||||
**Phase 1: Setup**
|
||||
```go
|
||||
func (party *Party) SignRound1(
|
||||
A structs.Matrix[ring.Poly],
|
||||
sid int,
|
||||
PRFKey []byte,
|
||||
T []int,
|
||||
) (structs.Matrix[ring.Poly], map[int][]byte) {
|
||||
// Generate randomness using PRF
|
||||
// Compute first round messages
|
||||
// Create MAC tags for other parties
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 2: Challenge Computation**
|
||||
```go
|
||||
func (party *Party) SignRound2(
|
||||
hintShares map[int]structs.Vector[uint8],
|
||||
) (structs.Vector[uint8], []byte) {
|
||||
// Aggregate hint shares
|
||||
// Compute ring signature challenge
|
||||
// Prepare response
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 3: Response Generation**
|
||||
```go
|
||||
func (party *Party) SignRound3(
|
||||
dShares map[int]structs.Matrix[ring.Poly],
|
||||
) structs.Matrix[ring.Poly] {
|
||||
// Combine shares from all parties
|
||||
// Generate final signature response
|
||||
// Clean up sensitive data
|
||||
}
|
||||
```
|
||||
|
||||
### Utilities Package
|
||||
|
||||
Helper functions for efficient operations:
|
||||
|
||||
```go
|
||||
// utils/utils.go
|
||||
package utils
|
||||
|
||||
// Matrix-vector multiplication in polynomial ring
|
||||
func MatrixVectorMul(
|
||||
r *ring.Ring,
|
||||
M structs.Matrix[ring.Poly],
|
||||
v structs.Vector[ring.Poly],
|
||||
result structs.Vector[ring.Poly],
|
||||
) {
|
||||
for i := 0; i < len(M); i++ {
|
||||
r.MulCoeffsMontgomery(M[i][0], v[0], result[i])
|
||||
for j := 1; j < len(v); j++ {
|
||||
r.MulCoeffsMontgomeryThenAdd(M[i][j], v[j], result[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NTT conversions for efficiency
|
||||
func ConvertVectorToNTT(r *ring.Ring, v structs.Vector[ring.Poly]) {
|
||||
for i := range v {
|
||||
r.NTT(v[i], v[i])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Ring Signature Implementation
|
||||
|
||||
### Key Generation
|
||||
|
||||
```go
|
||||
type RingMember struct {
|
||||
PublicKey *PublicKey
|
||||
PrivateKey *PrivateKey // nil for decoy members
|
||||
Index int // position in ring
|
||||
}
|
||||
|
||||
func GenerateKeyPair() (*PublicKey, *PrivateKey, error) {
|
||||
// Generate random private key
|
||||
priv, err := rand.Int(rand.Reader, curve.N)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Compute public key: P = x*G
|
||||
pub := new(PublicKey)
|
||||
pub.X, pub.Y = curve.ScalarBaseMult(priv.Bytes())
|
||||
|
||||
return pub, (*PrivateKey)(priv), nil
|
||||
}
|
||||
```
|
||||
|
||||
### Key Image Generation
|
||||
|
||||
```go
|
||||
func GenerateKeyImage(privKey *PrivateKey) *KeyImage {
|
||||
// Compute I = x * H(P)
|
||||
pubKey := privKey.PublicKey()
|
||||
hashPoint := HashToPoint(pubKey.Bytes())
|
||||
|
||||
keyImage := new(KeyImage)
|
||||
keyImage.X, keyImage.Y = curve.ScalarMult(
|
||||
hashPoint.X, hashPoint.Y,
|
||||
privKey.Bytes(),
|
||||
)
|
||||
|
||||
return keyImage
|
||||
}
|
||||
```
|
||||
|
||||
### Ring Construction
|
||||
|
||||
```go
|
||||
func ConstructRing(
|
||||
signerIndex int,
|
||||
signerPubKey *PublicKey,
|
||||
decoyKeys []*PublicKey,
|
||||
) []*PublicKey {
|
||||
ringSize := len(decoyKeys) + 1
|
||||
ring := make([]*PublicKey, ringSize)
|
||||
|
||||
// Place signer at specified index
|
||||
ring[signerIndex] = signerPubKey
|
||||
|
||||
// Fill remaining positions with decoys
|
||||
decoyIdx := 0
|
||||
for i := 0; i < ringSize; i++ {
|
||||
if i != signerIndex {
|
||||
ring[i] = decoyKeys[decoyIdx]
|
||||
decoyIdx++
|
||||
}
|
||||
}
|
||||
|
||||
return ring
|
||||
}
|
||||
```
|
||||
|
||||
### Signature Algorithm
|
||||
|
||||
```go
|
||||
func SignRing(
|
||||
message []byte,
|
||||
ring []*PublicKey,
|
||||
signerIndex int,
|
||||
privKey *PrivateKey,
|
||||
) (*RingSignature, error) {
|
||||
n := len(ring)
|
||||
sig := &RingSignature{
|
||||
KeyImage: GenerateKeyImage(privKey),
|
||||
RingPubKeys: ring,
|
||||
S: make([]*big.Int, n),
|
||||
}
|
||||
|
||||
// Generate random responses for non-signers
|
||||
c := make([]*big.Int, n)
|
||||
for i := 0; i < n; i++ {
|
||||
if i != signerIndex {
|
||||
sig.S[i], _ = rand.Int(rand.Reader, curve.N)
|
||||
c[i], _ = rand.Int(rand.Reader, curve.N)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate commitment
|
||||
alpha, _ := rand.Int(rand.Reader, curve.N)
|
||||
L := make([]*Point, n)
|
||||
R := make([]*Point, n)
|
||||
|
||||
// Compute L_i, R_i for signer
|
||||
L[signerIndex] = new(Point)
|
||||
L[signerIndex].X, L[signerIndex].Y = curve.ScalarBaseMult(alpha.Bytes())
|
||||
|
||||
R[signerIndex] = new(Point)
|
||||
hP := HashToPoint(ring[signerIndex].Bytes())
|
||||
R[signerIndex].X, R[signerIndex].Y = curve.ScalarMult(
|
||||
hP.X, hP.Y, alpha.Bytes(),
|
||||
)
|
||||
|
||||
// Compute L_j, R_j for non-signers
|
||||
for i := (signerIndex + 1) % n; i != signerIndex; i = (i + 1) % n {
|
||||
// L_j = s_j*G + c_j*P_j
|
||||
L[i] = computeL(sig.S[i], c[i], ring[i])
|
||||
// R_j = s_j*H(P_j) + c_j*I
|
||||
R[i] = computeR(sig.S[i], c[i], ring[i], sig.KeyImage)
|
||||
}
|
||||
|
||||
// Compute challenge
|
||||
sig.C0 = ChallengeHash(message, L, R)
|
||||
|
||||
// Close the ring
|
||||
cSum := new(big.Int)
|
||||
for i := 0; i < n; i++ {
|
||||
if i != signerIndex {
|
||||
cSum.Add(cSum, c[i])
|
||||
}
|
||||
}
|
||||
c[signerIndex] = new(big.Int).Sub(sig.C0, cSum)
|
||||
c[signerIndex].Mod(c[signerIndex], curve.N)
|
||||
|
||||
// Compute signer's response
|
||||
sig.S[signerIndex] = new(big.Int).Mul(c[signerIndex], privKey.Big())
|
||||
sig.S[signerIndex].Sub(alpha, sig.S[signerIndex])
|
||||
sig.S[signerIndex].Mod(sig.S[signerIndex], curve.N)
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Verification Algorithm
|
||||
|
||||
```go
|
||||
func VerifyRing(
|
||||
message []byte,
|
||||
sig *RingSignature,
|
||||
) bool {
|
||||
n := len(sig.RingPubKeys)
|
||||
L := make([]*Point, n)
|
||||
R := make([]*Point, n)
|
||||
|
||||
c := make([]*big.Int, n)
|
||||
c[0] = sig.C0
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
// Compute L_i = s_i*G + c_i*P_i
|
||||
L[i] = computeL(sig.S[i], c[i], sig.RingPubKeys[i])
|
||||
|
||||
// Compute R_i = s_i*H(P_i) + c_i*I
|
||||
R[i] = computeR(sig.S[i], c[i], sig.RingPubKeys[i], sig.KeyImage)
|
||||
|
||||
// Compute next challenge
|
||||
if i < n-1 {
|
||||
c[i+1] = ChallengeHash(message, L[i], R[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Verify ring closure
|
||||
finalChallenge := ChallengeHash(message, L, R)
|
||||
return finalChallenge.Cmp(sig.C0) == 0
|
||||
}
|
||||
```
|
||||
|
||||
## Lattice Integration
|
||||
|
||||
### Polynomial Operations
|
||||
|
||||
```go
|
||||
// Efficient polynomial multiplication using NTT
|
||||
func PolyMul(r *ring.Ring, a, b, c ring.Poly) {
|
||||
// Convert to NTT domain
|
||||
r.NTT(a, a)
|
||||
r.NTT(b, b)
|
||||
|
||||
// Component-wise multiplication
|
||||
r.MulCoeffsMontgomery(a, b, c)
|
||||
|
||||
// Convert back from NTT
|
||||
r.INTT(c, c)
|
||||
}
|
||||
|
||||
// Gaussian sampling for error polynomials
|
||||
func SampleGaussianPoly(r *ring.Ring, sigma float64) ring.Poly {
|
||||
sampler := ring.NewGaussianSampler(
|
||||
prng, r,
|
||||
ring.DiscreteGaussian{Sigma: sigma},
|
||||
false,
|
||||
)
|
||||
|
||||
poly := r.NewPoly()
|
||||
sampler.Read(poly)
|
||||
return poly
|
||||
}
|
||||
```
|
||||
|
||||
### Threshold Signatures
|
||||
|
||||
```go
|
||||
// Distributed signature generation
|
||||
type ThresholdSigner struct {
|
||||
Parties []*Party
|
||||
Threshold int
|
||||
PublicKey structs.Vector[ring.Poly]
|
||||
}
|
||||
|
||||
func (ts *ThresholdSigner) Sign(
|
||||
message []byte,
|
||||
signers []int,
|
||||
) (*ThresholdSignature, error) {
|
||||
if len(signers) < ts.Threshold {
|
||||
return nil, ErrInsufficientSigners
|
||||
}
|
||||
|
||||
// Round 1: Generate partial signatures
|
||||
round1Data := make(map[int]Round1Message)
|
||||
for _, id := range signers {
|
||||
data := ts.Parties[id].SignRound1(...)
|
||||
round1Data[id] = data
|
||||
}
|
||||
|
||||
// Round 2: Aggregate and compute challenge
|
||||
round2Data := make(map[int]Round2Message)
|
||||
for _, id := range signers {
|
||||
data := ts.Parties[id].SignRound2(round1Data)
|
||||
round2Data[id] = data
|
||||
}
|
||||
|
||||
// Round 3: Generate final signature
|
||||
signature := ts.combinePartialSignatures(round2Data)
|
||||
|
||||
return signature, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Network Protocol
|
||||
|
||||
### Message Types
|
||||
|
||||
```go
|
||||
type MessageType uint8
|
||||
|
||||
const (
|
||||
MsgKeyGenInit MessageType = iota
|
||||
MsgKeyGenShare
|
||||
MsgSignRound1
|
||||
MsgSignRound2
|
||||
MsgSignRound3
|
||||
MsgAbort
|
||||
)
|
||||
|
||||
type NetworkMessage struct {
|
||||
Type MessageType
|
||||
SessionID []byte
|
||||
PartyID int
|
||||
Data []byte
|
||||
MAC []byte
|
||||
}
|
||||
```
|
||||
|
||||
### Communication Layer
|
||||
|
||||
```go
|
||||
func (p *Party) Broadcast(msg NetworkMessage) error {
|
||||
// Add MAC for authentication
|
||||
msg.MAC = p.computeMAC(msg)
|
||||
|
||||
// Send to all parties
|
||||
for _, peer := range p.peers {
|
||||
if err := peer.Send(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Party) ReceiveMessages(
|
||||
expectedType MessageType,
|
||||
timeout time.Duration,
|
||||
) (map[int]NetworkMessage, error) {
|
||||
messages := make(map[int]NetworkMessage)
|
||||
deadline := time.Now().Add(timeout)
|
||||
|
||||
for time.Now().Before(deadline) {
|
||||
msg, err := p.network.Receive()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Verify MAC
|
||||
if !p.verifyMAC(msg) {
|
||||
return nil, ErrInvalidMAC
|
||||
}
|
||||
|
||||
// Check message type
|
||||
if msg.Type != expectedType {
|
||||
return nil, ErrUnexpectedMessage
|
||||
}
|
||||
|
||||
messages[msg.PartyID] = msg
|
||||
|
||||
if len(messages) == len(p.peers) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Memory Security
|
||||
|
||||
```go
|
||||
// Secure memory handling
|
||||
func (p *PrivateKey) Clear() {
|
||||
// Overwrite private key material
|
||||
bytes := p.Bytes()
|
||||
for i := range bytes {
|
||||
bytes[i] = 0
|
||||
}
|
||||
runtime.SetFinalizer(p, nil)
|
||||
}
|
||||
|
||||
// Use defer for cleanup
|
||||
func sensitiveOperation() {
|
||||
privKey := generatePrivateKey()
|
||||
defer privKey.Clear()
|
||||
|
||||
// Perform operations
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Randomness Quality
|
||||
|
||||
```go
|
||||
// Always use crypto/rand for security-critical operations
|
||||
import "crypto/rand"
|
||||
|
||||
func generateSecureRandom(size int) ([]byte, error) {
|
||||
bytes := make([]byte, size)
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("random generation failed: %w", err)
|
||||
}
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
// Deterministic randomness for reproducibility
|
||||
func deterministicRandom(seed []byte) *DeterministicRNG {
|
||||
h := sha256.Sum256(seed)
|
||||
return &DeterministicRNG{
|
||||
state: h[:],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Constant-Time Operations
|
||||
|
||||
```go
|
||||
// Avoid timing leaks
|
||||
func constantTimeCompare(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
var result byte
|
||||
for i := 0; i < len(a); i++ {
|
||||
result |= a[i] ^ b[i]
|
||||
}
|
||||
|
||||
return result == 0
|
||||
}
|
||||
|
||||
// Constant-time selection
|
||||
func constantTimeSelect(v, a, b *big.Int) *big.Int {
|
||||
// v = 1 -> return a
|
||||
// v = 0 -> return b
|
||||
mask := new(big.Int).Sub(v, big.NewInt(1))
|
||||
mask.Not(mask)
|
||||
|
||||
result := new(big.Int)
|
||||
result.And(a, mask)
|
||||
|
||||
tmp := new(big.Int)
|
||||
tmp.Not(mask)
|
||||
tmp.And(b, tmp)
|
||||
|
||||
result.Or(result, tmp)
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```go
|
||||
func TestRingSignature(t *testing.T) {
|
||||
// Setup
|
||||
ringSize := 16
|
||||
ring := generateTestRing(ringSize)
|
||||
signerIndex := 7
|
||||
privKey := testPrivateKeys[signerIndex]
|
||||
message := []byte("test message")
|
||||
|
||||
// Sign
|
||||
sig, err := SignRing(message, ring, signerIndex, privKey)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify
|
||||
valid := VerifyRing(message, sig)
|
||||
assert.True(t, valid)
|
||||
|
||||
// Test linkability
|
||||
sig2, _ := SignRing([]byte("another message"), ring, signerIndex, privKey)
|
||||
assert.Equal(t, sig.KeyImage, sig2.KeyImage)
|
||||
}
|
||||
```
|
||||
|
||||
### Benchmarks
|
||||
|
||||
```go
|
||||
func BenchmarkRingSign16(b *testing.B) {
|
||||
ring := generateTestRing(16)
|
||||
privKey := generatePrivateKey()
|
||||
message := []byte("benchmark message")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
SignRing(message, ring, 0, privKey)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRingVerify16(b *testing.B) {
|
||||
ring := generateTestRing(16)
|
||||
sig := generateTestSignature(ring)
|
||||
message := []byte("benchmark message")
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
VerifyRing(message, sig)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
```go
|
||||
func TestThresholdSigningProtocol(t *testing.T) {
|
||||
// Setup threshold parameters
|
||||
n := 7 // total parties
|
||||
threshold := 5 // threshold
|
||||
|
||||
// Initialize parties
|
||||
parties := setupParties(n, threshold)
|
||||
|
||||
// Select signers (must be >= threshold)
|
||||
signers := []int{0, 2, 3, 4, 6}
|
||||
|
||||
// Run protocol
|
||||
message := []byte("threshold test")
|
||||
sig, err := runThresholdProtocol(parties, signers, message)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.True(t, verifyThresholdSignature(message, sig))
|
||||
}
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Library Usage
|
||||
|
||||
```go
|
||||
import "github.com/luxfi/corona"
|
||||
|
||||
// Initialize Corona
|
||||
rt := corona.New(corona.Config{
|
||||
RingSize: 16,
|
||||
Algorithm: corona.AlgoSchnorr,
|
||||
HashFunction: sha256.New,
|
||||
Curve: elliptic.P256(),
|
||||
})
|
||||
|
||||
// Generate keys
|
||||
pub, priv, _ := rt.GenerateKeyPair()
|
||||
|
||||
// Create ring signature
|
||||
ring := rt.SelectRing(pub, 15) // 15 decoys + 1 signer
|
||||
sig, _ := rt.Sign(message, ring, priv)
|
||||
|
||||
// Verify signature
|
||||
valid := rt.Verify(message, sig)
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
// Ring parameters
|
||||
RingSize int // Number of ring members
|
||||
Algorithm Algorithm // Signature algorithm
|
||||
|
||||
// Lattice parameters
|
||||
PolyDegree int // Polynomial degree (power of 2)
|
||||
Modulus *big.Int // Ring modulus
|
||||
ErrorStdDev float64 // Gaussian error standard deviation
|
||||
|
||||
// Threshold parameters
|
||||
TotalParties int // Total number of parties
|
||||
Threshold int // Signing threshold
|
||||
|
||||
// Security parameters
|
||||
SecurityLevel int // Target security level in bits
|
||||
QuantumSafe bool // Enable post-quantum features
|
||||
|
||||
// Performance tuning
|
||||
ParallelOps bool // Enable parallel operations
|
||||
CacheSize int // Signature cache size
|
||||
BatchSize int // Batch verification size
|
||||
}
|
||||
```
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: Corona - Privacy-preserving ring signatures for the Lux blockchain
|
||||
---
|
||||
|
||||
# Corona
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- High performance
|
||||
- Production ready
|
||||
- Well tested
|
||||
- Comprehensive API
|
||||
|
||||
## Quick Start
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/luxfi/corona"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Your code here
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
Coming soon. For now, see the [source code](https://github.com/luxfi/corona).
|
||||
|
||||
## Next Steps
|
||||
|
||||
- API Reference
|
||||
- Examples
|
||||
- Configuration Guide
|
||||
@@ -1,440 +0,0 @@
|
||||
---
|
||||
title: Privacy Guarantees
|
||||
description: Understanding the privacy properties and security guarantees of Corona
|
||||
---
|
||||
|
||||
# Privacy Guarantees
|
||||
|
||||
## Overview
|
||||
|
||||
Corona provides strong privacy guarantees through a combination of cryptographic techniques. This document details the privacy properties, threat models, and security guarantees provided by the system.
|
||||
|
||||
## Privacy Properties
|
||||
|
||||
### 1. Signer Anonymity
|
||||
|
||||
**Property**: The identity of the actual signer is hidden among a set of potential signers (the ring).
|
||||
|
||||
**Guarantee Level**: **Unconditional**
|
||||
- Information-theoretic hiding
|
||||
- No computational assumptions required
|
||||
- Perfect indistinguishability among ring members
|
||||
|
||||
**Mathematical Foundation**:
|
||||
```
|
||||
For a ring R = {PK₁, PK₂, ..., PKₙ} and signature σ:
|
||||
Pr[Signer = PKᵢ | σ] = 1/n for all i ∈ [1,n]
|
||||
```
|
||||
|
||||
### 2. Unlinkability (Within Different Rings)
|
||||
|
||||
**Property**: Signatures using different rings cannot be linked to the same signer.
|
||||
|
||||
**Guarantee Level**: **Computational**
|
||||
- Based on Decisional Diffie-Hellman (DDH) assumption
|
||||
- Quantum resistance through lattice-based alternatives
|
||||
|
||||
**Formal Definition**:
|
||||
```
|
||||
For signatures σ₁ on ring R₁ and σ₂ on ring R₂:
|
||||
If R₁ ≠ R₂, then σ₁ and σ₂ are unlinkable
|
||||
```
|
||||
|
||||
### 3. Linkability (Within Same Context)
|
||||
|
||||
**Property**: Signatures from the same private key can be detected (preventing double-spending).
|
||||
|
||||
**Guarantee Level**: **Cryptographic**
|
||||
- Deterministic key image generation
|
||||
- Collision-resistant hash functions
|
||||
|
||||
**Key Image Property**:
|
||||
```
|
||||
KeyImage = x · H(P) where:
|
||||
- x is the private key
|
||||
- P is the public key
|
||||
- H is a hash-to-point function
|
||||
|
||||
Same x → Same KeyImage (always)
|
||||
Different x → Different KeyImage (with overwhelming probability)
|
||||
```
|
||||
|
||||
### 4. Non-frameability
|
||||
|
||||
**Property**: No party can forge a signature that appears to come from another party's private key.
|
||||
|
||||
**Guarantee Level**: **Computational**
|
||||
- Based on discrete logarithm assumption
|
||||
- Existential unforgeability under chosen message attack (EUF-CMA)
|
||||
|
||||
### 5. Forward Privacy
|
||||
|
||||
**Property**: Past signatures remain anonymous even if private keys are later compromised.
|
||||
|
||||
**Guarantee Level**: **Perfect**
|
||||
- Historical signatures cannot be de-anonymized
|
||||
- Key compromise doesn't reveal past signing patterns
|
||||
|
||||
## Threat Models
|
||||
|
||||
### Passive Adversary
|
||||
|
||||
**Capabilities**:
|
||||
- Observe all signatures on the blockchain
|
||||
- Analyze transaction patterns
|
||||
- Collect timing information
|
||||
|
||||
**Protection**:
|
||||
- Ring signatures hide signer identity
|
||||
- Key images prevent correlation attacks
|
||||
- Constant-time implementations prevent timing attacks
|
||||
|
||||
**Limitations**:
|
||||
- Cannot determine actual signer from signature
|
||||
- Cannot link signatures across different rings
|
||||
- Cannot predict future signatures
|
||||
|
||||
### Active Adversary
|
||||
|
||||
**Capabilities**:
|
||||
- Create malicious signatures
|
||||
- Attempt to forge signatures
|
||||
- Control some ring members
|
||||
|
||||
**Protection**:
|
||||
- Cryptographic unforgeability
|
||||
- Threshold requirements for multi-party signatures
|
||||
- MAC authentication in network protocols
|
||||
|
||||
**Attack Scenarios Protected Against**:
|
||||
1. **Sybil Attacks**: Controlling multiple ring members doesn't break anonymity
|
||||
2. **Chosen Ring Attacks**: Adversary cannot force specific ring compositions
|
||||
3. **Replay Attacks**: Unique challenges prevent signature replay
|
||||
|
||||
### Quantum Adversary
|
||||
|
||||
**Capabilities**:
|
||||
- Shor's algorithm for discrete logarithm
|
||||
- Grover's algorithm for search problems
|
||||
- Unlimited classical computation
|
||||
|
||||
**Protection (Hybrid Mode)**:
|
||||
- Lattice-based signatures (quantum-resistant)
|
||||
- Increased key sizes for Grover resistance
|
||||
- Post-quantum key exchange protocols
|
||||
|
||||
**Security Levels**:
|
||||
|
||||
| Component | Classical | Post-Quantum |
|
||||
|-----------|-----------|--------------|
|
||||
| Ring Signatures | 128-bit | 64-bit |
|
||||
| Lattice Signatures | 256-bit | 128-bit |
|
||||
| Hybrid Mode | 256-bit | 128-bit |
|
||||
|
||||
## Anonymity Set Analysis
|
||||
|
||||
### Ring Size Impact
|
||||
|
||||
The anonymity set size directly affects privacy:
|
||||
|
||||
| Ring Size | Anonymity | Storage Overhead | Verification Time |
|
||||
|-----------|-----------|------------------|-------------------|
|
||||
| 4 | 2 bits | 128 bytes | 0.5 ms |
|
||||
| 8 | 3 bits | 256 bytes | 1.0 ms |
|
||||
| 16 | 4 bits | 512 bytes | 1.8 ms |
|
||||
| 32 | 5 bits | 1024 bytes | 3.5 ms |
|
||||
| 64 | 6 bits | 2048 bytes | 7.0 ms |
|
||||
|
||||
**Recommended Minimum**: 16 members (4 bits of anonymity)
|
||||
|
||||
### Temporal Analysis Resistance
|
||||
|
||||
**Ring Member Selection Strategy**:
|
||||
```go
|
||||
func SelectRingMembers(currentHeight int) []*PublicKey {
|
||||
// Recent outputs (50%)
|
||||
recent := selectFromRange(currentHeight-100, currentHeight)
|
||||
|
||||
// Medium-term outputs (30%)
|
||||
medium := selectFromRange(currentHeight-1000, currentHeight-100)
|
||||
|
||||
// Historical outputs (20%)
|
||||
historical := selectFromRange(0, currentHeight-1000)
|
||||
|
||||
return shuffle(append(recent, medium, historical...))
|
||||
}
|
||||
```
|
||||
|
||||
### Statistical Disclosure Attacks
|
||||
|
||||
**Protection Measures**:
|
||||
1. **Uniform Distribution**: Ring members selected uniformly
|
||||
2. **Output Mixing**: Include outputs from different time periods
|
||||
3. **Value Similarity**: Select outputs with similar values
|
||||
4. **Churn Prevention**: Limit frequency of ring reuse
|
||||
|
||||
## Information Leakage Analysis
|
||||
|
||||
### What IS Revealed
|
||||
|
||||
1. **Key Image**: Unique identifier for double-spend detection
|
||||
2. **Ring Members**: The set of possible signers
|
||||
3. **Message**: The signed data (unless encrypted)
|
||||
4. **Timestamp**: When signature was created
|
||||
|
||||
### What is NOT Revealed
|
||||
|
||||
1. **Actual Signer**: Hidden among ring members
|
||||
2. **Private Key**: No information about secret key
|
||||
3. **Link Between Different Rings**: Unlinkable across contexts
|
||||
4. **Transaction Amount**: Can be hidden with Pedersen commitments
|
||||
|
||||
### Metadata Protection
|
||||
|
||||
**Network-Level Privacy**:
|
||||
```go
|
||||
// Use Tor/I2P for transaction broadcast
|
||||
func BroadcastTransaction(tx *Transaction) error {
|
||||
// Route through privacy network
|
||||
if config.UseTor {
|
||||
return broadcastViaTor(tx)
|
||||
}
|
||||
|
||||
// Add timing jitter
|
||||
delay := randomDelay(0, 60*time.Second)
|
||||
time.Sleep(delay)
|
||||
|
||||
// Broadcast to random subset of peers
|
||||
peers := selectRandomPeers(8)
|
||||
return broadcastToPeers(tx, peers)
|
||||
}
|
||||
```
|
||||
|
||||
## Cryptographic Assumptions
|
||||
|
||||
### Classical Security
|
||||
|
||||
**Discrete Logarithm Problem (DLP)**:
|
||||
- Given: `P = xG`
|
||||
- Find: `x`
|
||||
- Hardness: 2^128 operations for 256-bit curves
|
||||
|
||||
**Decisional Diffie-Hellman (DDH)**:
|
||||
- Distinguish: `(G, xG, yG, xyG)` from `(G, xG, yG, zG)`
|
||||
- Required for: Unlinkability between rings
|
||||
|
||||
**Hash Function Properties**:
|
||||
- Collision resistance: Cannot find `x ≠ y` where `H(x) = H(y)`
|
||||
- Preimage resistance: Given `h`, cannot find `x` where `H(x) = h`
|
||||
- Second preimage resistance: Given `x`, cannot find `y ≠ x` where `H(x) = H(y)`
|
||||
|
||||
### Post-Quantum Security
|
||||
|
||||
**Ring Learning With Errors (Ring-LWE)**:
|
||||
- Given: `(A, As + e)` for small error `e`
|
||||
- Find: Secret `s`
|
||||
- Hardness: Exponential in lattice dimension
|
||||
|
||||
**Module Learning With Errors (Module-LWE)**:
|
||||
- Generalization of Ring-LWE
|
||||
- Used in NIST standardized algorithms
|
||||
- Security parameter: 128-256 bits post-quantum
|
||||
|
||||
## Implementation Security
|
||||
|
||||
### Side-Channel Resistance
|
||||
|
||||
**Timing Attack Prevention**:
|
||||
```go
|
||||
// Constant-time scalar multiplication
|
||||
func constantTimeScalarMult(k *big.Int, P *Point) *Point {
|
||||
// Always perform same number of operations
|
||||
result := IdentityPoint()
|
||||
temp := P.Copy()
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
bit := k.Bit(i)
|
||||
// Conditional move, not branch
|
||||
result = conditionalAdd(result, temp, bit)
|
||||
temp = temp.Double()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
**Power Analysis Protection**:
|
||||
```go
|
||||
// Randomized computation order
|
||||
func protectedSign(msg []byte, ring []*PublicKey) *Signature {
|
||||
// Random blinding factor
|
||||
blind := randomScalar()
|
||||
|
||||
// Shuffle computation order
|
||||
order := randomPermutation(len(ring))
|
||||
|
||||
// Process in random order with blinding
|
||||
for _, idx := range order {
|
||||
processRingMember(idx, blind)
|
||||
}
|
||||
|
||||
// Remove blinding
|
||||
return unblind(signature, blind)
|
||||
}
|
||||
```
|
||||
|
||||
### Memory Security
|
||||
|
||||
**Secure Cleanup**:
|
||||
```go
|
||||
// Zero memory after use
|
||||
func (sk *PrivateKey) Clear() {
|
||||
bytes := sk.Bytes()
|
||||
|
||||
// Overwrite multiple times
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := range bytes {
|
||||
bytes[j] = byte(rand.Intn(256))
|
||||
}
|
||||
}
|
||||
|
||||
// Final zero
|
||||
for j := range bytes {
|
||||
bytes[j] = 0
|
||||
}
|
||||
|
||||
// Prevent compiler optimization
|
||||
runtime.KeepAlive(bytes)
|
||||
}
|
||||
```
|
||||
|
||||
## Privacy Best Practices
|
||||
|
||||
### For Developers
|
||||
|
||||
1. **Ring Selection**:
|
||||
- Use sufficient ring size (≥16)
|
||||
- Randomize ring member selection
|
||||
- Include diverse temporal distribution
|
||||
|
||||
2. **Key Management**:
|
||||
- Generate fresh keys for each identity
|
||||
- Secure key storage (HSM/TEE)
|
||||
- Regular key rotation
|
||||
|
||||
3. **Network Privacy**:
|
||||
- Use Tor/I2P for broadcast
|
||||
- Add random delays
|
||||
- Avoid correlatable patterns
|
||||
|
||||
### For Users
|
||||
|
||||
1. **Operational Security**:
|
||||
- Don't reuse addresses
|
||||
- Avoid temporal patterns
|
||||
- Use privacy-preserving networks
|
||||
|
||||
2. **Ring Hygiene**:
|
||||
- Verify ring size before signing
|
||||
- Check ring member diversity
|
||||
- Avoid rings with compromised keys
|
||||
|
||||
3. **Metadata Protection**:
|
||||
- Randomize transaction timing
|
||||
- Use different nodes for broadcast
|
||||
- Avoid correlatable amounts
|
||||
|
||||
## Formal Security Proofs
|
||||
|
||||
### Theorem 1: Signer Anonymity
|
||||
|
||||
**Statement**: For any PPT adversary A, the advantage in identifying the actual signer is negligible.
|
||||
|
||||
**Proof Sketch**:
|
||||
1. Ring signature is perfectly hiding
|
||||
2. All ring members equally likely
|
||||
3. Information-theoretic indistinguishability
|
||||
|
||||
### Theorem 2: Unforgeability
|
||||
|
||||
**Statement**: Under the DL assumption, no PPT adversary can forge a valid signature without the private key.
|
||||
|
||||
**Proof Sketch**:
|
||||
1. Reduction to discrete logarithm problem
|
||||
2. Forger implies DL solver
|
||||
3. Contradiction with DL hardness
|
||||
|
||||
### Theorem 3: Linkability
|
||||
|
||||
**Statement**: Signatures from the same key produce identical key images with probability 1.
|
||||
|
||||
**Proof**:
|
||||
1. Key image `I = xH(P)` is deterministic
|
||||
2. Same `x` always produces same `I`
|
||||
3. Different `x` produces different `I` (except negligible probability)
|
||||
|
||||
## Audit and Compliance
|
||||
|
||||
### Selective Disclosure
|
||||
|
||||
**View Keys**:
|
||||
```go
|
||||
type ViewKey struct {
|
||||
KeyImage *KeyImage
|
||||
PrivateView *big.Int
|
||||
}
|
||||
|
||||
// Allow auditor to verify specific signatures
|
||||
func (vk *ViewKey) VerifyOwnership(sig *RingSignature) bool {
|
||||
return vk.KeyImage.Equal(sig.KeyImage)
|
||||
}
|
||||
```
|
||||
|
||||
### Compliance Features
|
||||
|
||||
1. **Time-locked Disclosure**: Keys revealed after specific time
|
||||
2. **Threshold Disclosure**: Multiple parties required for reveal
|
||||
3. **Regulatory Reporting**: Aggregate statistics without individual privacy loss
|
||||
|
||||
### Zero-Knowledge Proofs
|
||||
|
||||
**Proof of Assets**:
|
||||
```go
|
||||
// Prove ownership without revealing which signatures
|
||||
func ProveAssets(amount *big.Int, signatures []*RingSignature) *ZKProof {
|
||||
// Generate commitment to total
|
||||
commitment := PedersenCommit(amount)
|
||||
|
||||
// Create range proof
|
||||
rangeProof := BulletproofRange(amount)
|
||||
|
||||
// Link to signatures without revealing which
|
||||
ownershipProof := ProveRingOwnership(signatures)
|
||||
|
||||
return &ZKProof{
|
||||
Commitment: commitment,
|
||||
Range: rangeProof,
|
||||
Ownership: ownershipProof,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Advanced Privacy Features
|
||||
|
||||
1. **Stealth Addresses**: One-time addresses for receivers
|
||||
2. **Confidential Assets**: Hide asset types
|
||||
3. **Private Smart Contracts**: Compute on encrypted data
|
||||
4. **Coinjoin Integration**: Additional mixing layer
|
||||
|
||||
### Research Directions
|
||||
|
||||
1. **Sublinear Ring Signatures**: O(log n) verification
|
||||
2. **Updatable Anonymity Sets**: Dynamic ring membership
|
||||
3. **Cross-Chain Privacy**: Universal anonymity pools
|
||||
4. **Quantum-Safe Variants**: Full post-quantum security
|
||||
|
||||
## Conclusion
|
||||
|
||||
Corona provides strong, provable privacy guarantees suitable for financial privacy applications. The combination of ring signatures for anonymity, key images for double-spend prevention, and lattice cryptography for post-quantum security creates a robust privacy system resistant to current and future threats.
|
||||
@@ -1,209 +0,0 @@
|
||||
---
|
||||
title: Ring Signatures
|
||||
description: Understanding Corona's ring signature implementation for privacy-preserving transactions
|
||||
---
|
||||
|
||||
# Ring Signatures in Corona
|
||||
|
||||
## Overview
|
||||
|
||||
Corona implements **linkable ring signatures** based on the Schnorr signature scheme, providing transaction privacy while maintaining the ability to detect double-spending. This cryptographic primitive enables users to prove membership in a group without revealing their specific identity.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Anonymity Set
|
||||
The **ring** consists of multiple public keys where:
|
||||
- One key belongs to the actual signer
|
||||
- Other keys are "decoys" that provide plausible deniability
|
||||
- Default ring size: 16 members (configurable)
|
||||
- Larger rings provide stronger privacy but increase computational cost
|
||||
|
||||
### Linkability
|
||||
While ring signatures hide the signer's identity, linkability ensures:
|
||||
- The same private key cannot sign twice for the same context
|
||||
- Double-spending prevention in cryptocurrency applications
|
||||
- Key images uniquely identify signatures from the same private key
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
### Core Components
|
||||
|
||||
```go
|
||||
// Ring signature structure
|
||||
type RingSignature struct {
|
||||
C0 *big.Int // Initial challenge
|
||||
S []*big.Int // Response values for each ring member
|
||||
KeyImage *Point // Unique identifier preventing double-signing
|
||||
RingPubKeys []*PublicKey // Public keys forming the ring
|
||||
}
|
||||
```
|
||||
|
||||
### Algorithm Overview
|
||||
|
||||
1. **Key Image Generation**: `I = x * H(P)` where:
|
||||
- `x` is the signer's private key
|
||||
- `P` is the signer's public key
|
||||
- `H()` is a hash-to-curve function
|
||||
|
||||
2. **Ring Construction**: Aggregate public keys from:
|
||||
- The actual signer
|
||||
- Randomly selected decoy keys
|
||||
- Order is randomized to hide signer position
|
||||
|
||||
3. **Signature Generation**:
|
||||
- Generate random nonces for each ring member
|
||||
- Compute challenges using hash chain
|
||||
- Create responses that satisfy verification equation
|
||||
|
||||
4. **Verification**: Check that:
|
||||
- All responses are valid
|
||||
- Challenge chain closes properly
|
||||
- Key image is well-formed
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Signature Size
|
||||
- Base size: 32 bytes × ring size
|
||||
- Default (16 members): 512 bytes
|
||||
- Scales linearly with ring size
|
||||
|
||||
### Performance Characteristics
|
||||
- **Sign time**: O(n) where n = ring size
|
||||
- **Verify time**: O(n)
|
||||
- **Space complexity**: O(n)
|
||||
|
||||
### Security Parameters
|
||||
- **Curve**: secp256k1 or Ed25519
|
||||
- **Hash function**: SHA-256
|
||||
- **Challenge size**: 256 bits
|
||||
- **Response size**: 256 bits per ring member
|
||||
|
||||
## Integration with Lattice Cryptography
|
||||
|
||||
Corona uniquely combines ring signatures with lattice-based cryptography from the Lattice library:
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/luxfi/lattice/v6/ring"
|
||||
"github.com/luxfi/lattice/v6/utils/sampling"
|
||||
)
|
||||
```
|
||||
|
||||
### Polynomial Ring Operations
|
||||
- Uses polynomial rings for efficient modular arithmetic
|
||||
- NTT (Number Theoretic Transform) for fast polynomial multiplication
|
||||
- Gaussian sampling for noise generation
|
||||
|
||||
### Threshold Signatures
|
||||
- Shamir secret sharing for distributed key generation
|
||||
- `t-of-n` threshold schemes supported
|
||||
- Secure multiparty computation protocols
|
||||
|
||||
## Privacy Guarantees
|
||||
|
||||
### Unconditional Anonymity
|
||||
- **Signer ambiguity**: Equal probability for each ring member
|
||||
- **Perfect hiding**: No information theoretic advantage
|
||||
- **Forward secrecy**: Past signatures remain anonymous even if keys are compromised
|
||||
|
||||
### Resistance to Analysis
|
||||
- **Timing attacks**: Constant-time implementations
|
||||
- **Side channels**: Protected against power analysis
|
||||
- **Blockchain analysis**: Ring signatures break transaction graph analysis
|
||||
|
||||
## Use Cases in Q-Chain
|
||||
|
||||
### Private Transactions
|
||||
- Hide sender identity in value transfers
|
||||
- Preserve receiver privacy through stealth addresses
|
||||
- Maintain public verifiability of transaction validity
|
||||
|
||||
### Confidential Smart Contracts
|
||||
- Anonymous voting systems
|
||||
- Private auctions
|
||||
- Confidential DeFi operations
|
||||
|
||||
### Regulatory Compliance
|
||||
- Optional view keys for authorized auditing
|
||||
- Selective disclosure capabilities
|
||||
- Compliance with privacy regulations
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Ring Selection
|
||||
1. **Size considerations**:
|
||||
- Minimum: 8 members for basic privacy
|
||||
- Recommended: 16 members for strong privacy
|
||||
- Maximum: 64 members (performance consideration)
|
||||
|
||||
2. **Member selection**:
|
||||
- Random sampling from active users
|
||||
- Temporal proximity (recent transactions)
|
||||
- Value similarity (similar transaction amounts)
|
||||
|
||||
### Key Management
|
||||
- Secure storage of private keys
|
||||
- Regular key rotation for long-term privacy
|
||||
- Backup strategies for key recovery
|
||||
|
||||
### Performance Optimization
|
||||
- Cache polynomial operations
|
||||
- Batch verification for multiple signatures
|
||||
- Parallel signature generation
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Known Attacks and Mitigations
|
||||
1. **Key image analysis**: Use deterministic key image generation
|
||||
2. **Ring intersection attacks**: Ensure sufficient ring overlap
|
||||
3. **Timing analysis**: Implement constant-time operations
|
||||
4. **Quantum threats**: Combined with post-quantum signatures
|
||||
|
||||
### Audit Trail
|
||||
- Key images provide spending auditability
|
||||
- Optional transaction memos for compliance
|
||||
- Cryptographic proofs of non-double-spending
|
||||
|
||||
## Code Example
|
||||
|
||||
```go
|
||||
// Generate a ring signature
|
||||
func SignWithRing(message []byte, privateKey *PrivateKey, ring []*PublicKey) (*RingSignature, error) {
|
||||
// Generate key image
|
||||
keyImage := GenerateKeyImage(privateKey)
|
||||
|
||||
// Create signature components
|
||||
sig := &RingSignature{
|
||||
KeyImage: keyImage,
|
||||
RingPubKeys: ring,
|
||||
S: make([]*big.Int, len(ring)),
|
||||
}
|
||||
|
||||
// Generate signature using Schnorr-based ring signature
|
||||
// ... (implementation details)
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// Verify a ring signature
|
||||
func VerifyRingSignature(message []byte, sig *RingSignature) bool {
|
||||
// Verify challenge chain
|
||||
// Check key image validity
|
||||
// Validate responses
|
||||
return valid
|
||||
}
|
||||
```
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned Features
|
||||
- **Bulletproofs integration**: Confidential amounts with ring signatures
|
||||
- **Sublinear ring signatures**: Logarithmic signature size
|
||||
- **Multi-ring signatures**: Cross-chain privacy
|
||||
- **Zero-knowledge range proofs**: Amount privacy
|
||||
|
||||
### Research Directions
|
||||
- Post-quantum ring signatures
|
||||
- Efficient batch verification
|
||||
- Ring signature aggregation
|
||||
- Threshold ring signatures
|
||||
@@ -1,299 +0,0 @@
|
||||
---
|
||||
title: Cryptographic Theory
|
||||
description: Mathematical foundations of linkable ring signatures and lattice-based cryptography
|
||||
---
|
||||
|
||||
# Cryptographic Theory
|
||||
|
||||
## Overview
|
||||
|
||||
Corona combines two powerful cryptographic primitives: **linkable ring signatures** for privacy and **lattice-based cryptography** for post-quantum security. This unique combination provides both strong privacy guarantees and resistance to quantum attacks.
|
||||
|
||||
## Ring Signature Mathematics
|
||||
|
||||
### Schnorr Signature Foundation
|
||||
|
||||
Corona's ring signatures are based on the Schnorr signature scheme, which provides:
|
||||
- **Simplicity**: Elegant mathematical structure
|
||||
- **Security**: Proven secure under discrete logarithm assumption
|
||||
- **Efficiency**: Fast signature generation and verification
|
||||
|
||||
#### Standard Schnorr Signature
|
||||
|
||||
For a message `m`, private key `x`, and public key `P = xG`:
|
||||
|
||||
1. **Sign**:
|
||||
- Choose random `k ∈ Zq`
|
||||
- Compute `R = kG`
|
||||
- Compute `e = H(R || P || m)`
|
||||
- Compute `s = k + ex`
|
||||
- Signature: `σ = (R, s)`
|
||||
|
||||
2. **Verify**:
|
||||
- Check: `sG = R + eP`
|
||||
|
||||
### Extension to Ring Signatures
|
||||
|
||||
Ring signatures extend Schnorr signatures to hide the signer among a ring of public keys.
|
||||
|
||||
#### Ring Signature Generation
|
||||
|
||||
Given:
|
||||
- Message `m`
|
||||
- Private key `xi` with public key `Pi`
|
||||
- Ring of public keys `{P0, P1, ..., Pn-1}`
|
||||
|
||||
Algorithm:
|
||||
```
|
||||
1. Generate key image: I = xi * H(Pi)
|
||||
2. For j ≠ i:
|
||||
- Choose random sj ∈ Zq
|
||||
- Choose random cj ∈ Zq
|
||||
3. Choose random α ∈ Zq
|
||||
4. Compute:
|
||||
- Li = αG
|
||||
- Ri = α * H(Pi)
|
||||
5. For j = i+1, ..., n-1, 0, ..., i-1:
|
||||
- Lj = sjG + cjPj
|
||||
- Rj = sjH(Pj) + cjI
|
||||
6. Compute challenge:
|
||||
c0 = H(m || L0 || ... || Ln-1 || R0 || ... || Rn-1)
|
||||
7. Close the ring:
|
||||
ci = c0 - Σ(j≠i) cj
|
||||
si = α - cixi
|
||||
8. Output: σ = (I, c0, s0, ..., sn-1)
|
||||
```
|
||||
|
||||
#### Ring Signature Verification
|
||||
|
||||
Given signature `σ = (I, c0, s0, ..., sn-1)`:
|
||||
|
||||
```
|
||||
1. For j = 0, ..., n-1:
|
||||
- Compute Lj' = sjG + cjPj
|
||||
- Compute Rj' = sjH(Pj) + cjI
|
||||
2. Verify: c0 = H(m || L0' || ... || Ln-1' || R0' || ... || Rn-1')
|
||||
```
|
||||
|
||||
### Linkability Property
|
||||
|
||||
The **key image** `I = x * H(P)` ensures linkability:
|
||||
- Deterministic for a given private key
|
||||
- Cannot be forged without knowledge of `x`
|
||||
- Two signatures with the same `I` indicate double-signing
|
||||
|
||||
This property is crucial for preventing double-spending in cryptocurrency applications.
|
||||
|
||||
## Lattice-Based Cryptography
|
||||
|
||||
### Polynomial Rings
|
||||
|
||||
Corona leverages polynomial ring operations from the Lattice library:
|
||||
|
||||
#### Ring Definition
|
||||
The ring `R = Z[X]/(X^n + 1)` where:
|
||||
- `n` is a power of 2 (typically 2^12 to 2^14)
|
||||
- Operations are performed modulo `q` (prime or power of prime)
|
||||
|
||||
#### Why Polynomial Rings?
|
||||
|
||||
1. **Efficiency**: NTT enables O(n log n) multiplication
|
||||
2. **Security**: Based on Ring-LWE problem
|
||||
3. **Structure**: Natural for threshold cryptography
|
||||
|
||||
### Number Theoretic Transform (NTT)
|
||||
|
||||
NTT is the finite field analogue of FFT:
|
||||
|
||||
```
|
||||
Forward NTT: a(X) → â = NTT(a)
|
||||
Inverse NTT: â → a(X) = NTT^(-1)(â)
|
||||
Multiplication: a(X) * b(X) = NTT^(-1)(NTT(a) ⊙ NTT(b))
|
||||
```
|
||||
|
||||
Where `⊙` denotes component-wise multiplication.
|
||||
|
||||
### Ring-LWE Problem
|
||||
|
||||
The security of lattice operations is based on the Ring Learning With Errors (Ring-LWE) problem:
|
||||
|
||||
Given `(A, b = As + e)` where:
|
||||
- `A` is a random polynomial matrix
|
||||
- `s` is a secret polynomial vector
|
||||
- `e` is a small error polynomial
|
||||
|
||||
It is computationally hard to recover `s`.
|
||||
|
||||
## Threshold Signatures
|
||||
|
||||
### Shamir Secret Sharing
|
||||
|
||||
Corona implements `(t, n)` threshold signatures using polynomial secret sharing:
|
||||
|
||||
#### Share Generation
|
||||
For secret `s` and threshold `t`:
|
||||
1. Generate random polynomial `f(x) = s + a₁x + ... + aₜ₋₁x^(t-1)`
|
||||
2. Compute shares: `sᵢ = f(i)` for `i = 1, ..., n`
|
||||
3. Any `t` shares can reconstruct `s` using Lagrange interpolation
|
||||
|
||||
#### Lagrange Interpolation
|
||||
```
|
||||
s = Σᵢ sᵢ * λᵢ
|
||||
where λᵢ = Π(j≠i) (j/(j-i))
|
||||
```
|
||||
|
||||
### Distributed Key Generation (DKG)
|
||||
|
||||
Corona supports distributed key generation without trusted dealer:
|
||||
|
||||
1. **Share Distribution**: Each party generates and distributes shares
|
||||
2. **Verification**: Feldman VSS ensures share validity
|
||||
3. **Aggregation**: Combine shares to form distributed key
|
||||
4. **Threshold Signing**: `t` parties collaborate to sign
|
||||
|
||||
## Security Analysis
|
||||
|
||||
### Privacy Guarantees
|
||||
|
||||
#### Unconditional Anonymity
|
||||
- **Information-theoretic hiding**: Even computationally unbounded adversary cannot identify signer
|
||||
- **Perfect indistinguishability**: All ring members equally likely
|
||||
- **Statistical distance**: Negligible between different signers
|
||||
|
||||
#### Unforgeability
|
||||
Under the discrete logarithm assumption:
|
||||
- Cannot forge signature without private key
|
||||
- Cannot create valid key image without secret
|
||||
- Collision-resistant hash functions prevent replay
|
||||
|
||||
### Quantum Resistance
|
||||
|
||||
#### Post-Quantum Security Levels
|
||||
|
||||
| Algorithm | Classical Security | Quantum Security |
|
||||
|-----------|-------------------|------------------|
|
||||
| Ring Signatures (256-bit) | 128 bits | 64 bits |
|
||||
| Ring-LWE (n=4096, q≈2^128) | 256 bits | 128 bits |
|
||||
| Hybrid Mode | 256 bits | 128 bits |
|
||||
|
||||
#### Quantum Attack Vectors
|
||||
|
||||
1. **Grover's Algorithm**: √n speedup for discrete log
|
||||
- Mitigation: Double key sizes
|
||||
|
||||
2. **Shor's Algorithm**: Polynomial time for discrete log
|
||||
- Mitigation: Lattice-based alternatives
|
||||
|
||||
3. **Hybrid Approach**: Combine classical and post-quantum
|
||||
- Current signatures remain valid
|
||||
- Future signatures gain quantum resistance
|
||||
|
||||
## Performance Analysis
|
||||
|
||||
### Computational Complexity
|
||||
|
||||
| Operation | Ring Signature | Lattice Operations |
|
||||
|-----------|---------------|-------------------|
|
||||
| Key Generation | O(1) | O(n log n) |
|
||||
| Sign | O(r) | O(n log n) |
|
||||
| Verify | O(r) | O(n log n) |
|
||||
| Key Image | O(1) | N/A |
|
||||
|
||||
Where:
|
||||
- `r` = ring size
|
||||
- `n` = polynomial degree
|
||||
|
||||
### Space Complexity
|
||||
|
||||
| Component | Size |
|
||||
|-----------|------|
|
||||
| Public Key | 32 bytes |
|
||||
| Private Key | 32 bytes |
|
||||
| Ring Signature | 32 + 32r bytes |
|
||||
| Lattice Signature | ~10 KB |
|
||||
| Key Image | 32 bytes |
|
||||
|
||||
### Benchmark Results
|
||||
|
||||
On Apple M1 Pro:
|
||||
- **Ring Sign (16 members)**: 2.1 ms
|
||||
- **Ring Verify (16 members)**: 1.8 ms
|
||||
- **Lattice Sign**: 0.8 ms
|
||||
- **Lattice Verify**: 0.4 ms
|
||||
- **Hybrid Sign**: 2.9 ms
|
||||
- **Hybrid Verify**: 2.2 ms
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
### Bulletproofs Integration
|
||||
|
||||
Corona can be extended with Bulletproofs for:
|
||||
- **Confidential amounts**: Hide transaction values
|
||||
- **Range proofs**: Prove values are in valid range
|
||||
- **Aggregation**: Combine multiple proofs
|
||||
|
||||
### Sublinear Ring Signatures
|
||||
|
||||
Future enhancement using techniques like:
|
||||
- **LSAG**: Linkable Spontaneous Anonymous Group signatures
|
||||
- **Omniring**: O(log n) verification time
|
||||
- **RingCT 3.0**: Logarithmic size signatures
|
||||
|
||||
### Cross-Chain Privacy
|
||||
|
||||
Multi-ring signatures for:
|
||||
- **Atomic swaps**: Private cross-chain exchanges
|
||||
- **Bridge privacy**: Hide cross-chain transfers
|
||||
- **Universal anonymity**: Single anonymity set across chains
|
||||
|
||||
## Implementation Considerations
|
||||
|
||||
### Side-Channel Protection
|
||||
|
||||
1. **Constant-time operations**: No data-dependent branches
|
||||
2. **Memory access patterns**: Independent of secret data
|
||||
3. **Power analysis**: Randomized computation order
|
||||
4. **Cache timing**: Preload all ring members
|
||||
|
||||
### Random Number Generation
|
||||
|
||||
Critical for security:
|
||||
```go
|
||||
// Use crypto/rand for security-critical randomness
|
||||
import "crypto/rand"
|
||||
|
||||
func generateNonce() (*big.Int, error) {
|
||||
max := new(big.Int).Sub(curve.N, big.NewInt(1))
|
||||
k, err := rand.Int(rand.Reader, max)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return k, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
Proper error propagation without leaking information:
|
||||
- Generic error messages
|
||||
- Timing-independent error paths
|
||||
- No correlation between errors and secrets
|
||||
|
||||
## References
|
||||
|
||||
### Academic Papers
|
||||
1. "Linkable Spontaneous Anonymous Group Signature" - Liu et al.
|
||||
2. "Ring Confidential Transactions" - Noether et al.
|
||||
3. "Lattice-based Zero-Knowledge Proofs" - Lyubashevsky
|
||||
4. "Post-Quantum Ring Signatures" - Torres et al.
|
||||
|
||||
### Standards
|
||||
- NIST Post-Quantum Cryptography
|
||||
- IETF Ring Signatures Draft
|
||||
- ISO/IEC 29192-7 Lightweight Cryptography
|
||||
|
||||
### Implementation Resources
|
||||
- Monero RingCT
|
||||
- Lattice Cryptography Library
|
||||
- Stanford IBE Implementation
|
||||
- Microsoft SEAL Library
|
||||
@@ -1,730 +0,0 @@
|
||||
---
|
||||
title: Usage Examples
|
||||
description: Practical examples and code samples for using Corona
|
||||
---
|
||||
|
||||
# Usage Examples
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Install Corona library
|
||||
go get github.com/luxfi/corona
|
||||
|
||||
# Install dependencies
|
||||
go get github.com/luxfi/lattice/v6
|
||||
```
|
||||
|
||||
### Basic Setup
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/luxfi/corona"
|
||||
"github.com/luxfi/corona/primitives"
|
||||
"github.com/luxfi/corona/sign"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize Corona with default configuration
|
||||
rt := corona.New(corona.DefaultConfig())
|
||||
|
||||
fmt.Println("Corona initialized successfully")
|
||||
}
|
||||
```
|
||||
|
||||
## Simple Ring Signature
|
||||
|
||||
### Generate Keys and Create Signature
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func simpleRingSignatureExample() {
|
||||
// 1. Generate key pairs for ring members
|
||||
ringSize := 16
|
||||
publicKeys := make([]*PublicKey, ringSize)
|
||||
|
||||
// Generate keys for all ring members
|
||||
var signerPrivKey *PrivateKey
|
||||
signerIndex := 7 // The actual signer will be at index 7
|
||||
|
||||
for i := 0; i < ringSize; i++ {
|
||||
pub, priv, err := GenerateKeyPair()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
publicKeys[i] = pub
|
||||
|
||||
// Keep the private key for the actual signer
|
||||
if i == signerIndex {
|
||||
signerPrivKey = priv
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Create a message to sign
|
||||
message := []byte("Transfer 100 LUX to address xyz")
|
||||
|
||||
// 3. Generate the ring signature
|
||||
signature, err := SignRing(
|
||||
message,
|
||||
publicKeys,
|
||||
signerIndex,
|
||||
signerPrivKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 4. Verify the signature
|
||||
valid := VerifyRing(message, signature)
|
||||
fmt.Printf("Signature valid: %v\n", valid)
|
||||
|
||||
// 5. Check signature size
|
||||
sigSize := signature.Size()
|
||||
fmt.Printf("Signature size: %d bytes\n", sigSize)
|
||||
|
||||
// 6. Demonstrate linkability
|
||||
message2 := []byte("Another transaction")
|
||||
signature2, _ := SignRing(message2, publicKeys, signerIndex, signerPrivKey)
|
||||
|
||||
// Both signatures have the same key image
|
||||
if signature.KeyImage.Equal(signature2.KeyImage) {
|
||||
fmt.Println("Signatures are linkable (same signer)")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Privacy-Preserving Transaction
|
||||
|
||||
### Confidential Transfer with Ring Signatures
|
||||
|
||||
```go
|
||||
type ConfidentialTransaction struct {
|
||||
Inputs []TxInput
|
||||
Outputs []TxOutput
|
||||
RingSize int
|
||||
Signatures []*RingSignature
|
||||
}
|
||||
|
||||
type TxInput struct {
|
||||
Amount uint64
|
||||
KeyImage *KeyImage
|
||||
RingMembers []*PublicKey
|
||||
}
|
||||
|
||||
type TxOutput struct {
|
||||
Amount uint64
|
||||
Recipient *PublicKey
|
||||
Ephemeral *PublicKey // For stealth address
|
||||
}
|
||||
|
||||
func createConfidentialTransaction() (*ConfidentialTransaction, error) {
|
||||
// 1. Select inputs (previous outputs we own)
|
||||
inputs := []TxInput{
|
||||
{
|
||||
Amount: 100,
|
||||
KeyImage: nil, // Will be set by signature
|
||||
},
|
||||
}
|
||||
|
||||
// 2. Create ring for input
|
||||
ringSize := 16
|
||||
ring := selectRingMembers(ringSize)
|
||||
inputs[0].RingMembers = ring
|
||||
|
||||
// 3. Create outputs with stealth addresses
|
||||
outputs := []TxOutput{
|
||||
{
|
||||
Amount: 90, // Send 90
|
||||
Recipient: generateStealthAddress(recipientPubKey),
|
||||
},
|
||||
{
|
||||
Amount: 10, // Change
|
||||
Recipient: generateStealthAddress(ownPubKey),
|
||||
},
|
||||
}
|
||||
|
||||
// 4. Create transaction
|
||||
tx := &ConfidentialTransaction{
|
||||
Inputs: inputs,
|
||||
Outputs: outputs,
|
||||
RingSize: ringSize,
|
||||
}
|
||||
|
||||
// 5. Sign each input with ring signature
|
||||
for i, input := range tx.Inputs {
|
||||
message := tx.HashForSigning(i)
|
||||
|
||||
sig, err := SignRing(
|
||||
message,
|
||||
input.RingMembers,
|
||||
myIndex,
|
||||
myPrivKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tx.Signatures = append(tx.Signatures, sig)
|
||||
tx.Inputs[i].KeyImage = sig.KeyImage
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
func (tx *ConfidentialTransaction) Verify() bool {
|
||||
// 1. Check balance (inputs = outputs)
|
||||
if !tx.checkBalance() {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. Verify each ring signature
|
||||
for i, sig := range tx.Signatures {
|
||||
message := tx.HashForSigning(i)
|
||||
if !VerifyRing(message, sig) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Check for double-spending (unique key images)
|
||||
keyImages := make(map[string]bool)
|
||||
for _, input := range tx.Inputs {
|
||||
ki := input.KeyImage.String()
|
||||
if keyImages[ki] {
|
||||
return false // Double spend detected
|
||||
}
|
||||
keyImages[ki] = true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
## Threshold Ring Signatures
|
||||
|
||||
### Multi-Party Signing Protocol
|
||||
|
||||
```go
|
||||
func thresholdRingSignatureExample() error {
|
||||
// Setup: 3-of-5 threshold with 16-member ring
|
||||
n := 5 // Total parties
|
||||
threshold := 3 // Minimum signers
|
||||
ringSize := 16
|
||||
|
||||
// 1. Initialize parties
|
||||
parties := make([]*sign.Party, n)
|
||||
for i := 0; i < n; i++ {
|
||||
parties[i] = initializeParty(i)
|
||||
}
|
||||
|
||||
// 2. Distributed Key Generation (DKG)
|
||||
fmt.Println("Starting DKG protocol...")
|
||||
|
||||
publicKey, keyShares, err := runDKG(parties)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DKG failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Group public key generated: %x\n", publicKey.Bytes())
|
||||
|
||||
// 3. Distribute key shares to parties
|
||||
for i, party := range parties {
|
||||
party.SetKeyShare(keyShares[i])
|
||||
}
|
||||
|
||||
// 4. Select subset of parties for signing (must be >= threshold)
|
||||
signers := []int{0, 2, 4} // Parties 0, 2, and 4 will sign
|
||||
|
||||
// 5. Create ring with decoy members
|
||||
ring := make([]*PublicKey, ringSize)
|
||||
ring[0] = publicKey // Group's public key
|
||||
for i := 1; i < ringSize; i++ {
|
||||
ring[i] = generateDecoyKey()
|
||||
}
|
||||
|
||||
// 6. Execute threshold signing protocol
|
||||
message := []byte("Threshold signed message")
|
||||
|
||||
signature, err := executeThresholdSigning(
|
||||
message,
|
||||
ring,
|
||||
parties,
|
||||
signers,
|
||||
threshold,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("threshold signing failed: %w", err)
|
||||
}
|
||||
|
||||
// 7. Verify the threshold ring signature
|
||||
valid := VerifyThresholdRingSignature(message, signature)
|
||||
fmt.Printf("Threshold ring signature valid: %v\n", valid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeThresholdSigning(
|
||||
message []byte,
|
||||
ring []*PublicKey,
|
||||
parties []*sign.Party,
|
||||
signers []int,
|
||||
threshold int,
|
||||
) (*ThresholdRingSignature, error) {
|
||||
// Round 1: Generate commitments
|
||||
round1Messages := make(map[int]Round1Message)
|
||||
|
||||
for _, id := range signers {
|
||||
msg, err := parties[id].SignRound1(message, ring)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
round1Messages[id] = msg
|
||||
}
|
||||
|
||||
// Broadcast round 1 messages
|
||||
for _, id := range signers {
|
||||
parties[id].ReceiveRound1(round1Messages)
|
||||
}
|
||||
|
||||
// Round 2: Generate shares
|
||||
round2Messages := make(map[int]Round2Message)
|
||||
|
||||
for _, id := range signers {
|
||||
msg, err := parties[id].SignRound2()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
round2Messages[id] = msg
|
||||
}
|
||||
|
||||
// Broadcast round 2 messages
|
||||
for _, id := range signers {
|
||||
parties[id].ReceiveRound2(round2Messages)
|
||||
}
|
||||
|
||||
// Round 3: Combine shares
|
||||
var signature *ThresholdRingSignature
|
||||
|
||||
for _, id := range signers {
|
||||
sig, err := parties[id].SignRound3()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if signature == nil {
|
||||
signature = sig
|
||||
}
|
||||
}
|
||||
|
||||
return signature, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Lattice-Based Ring Signatures
|
||||
|
||||
### Post-Quantum Secure Implementation
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/luxfi/lattice/v6/ring"
|
||||
"github.com/luxfi/lattice/v6/utils/sampling"
|
||||
)
|
||||
|
||||
func latticeRingSignatureExample() {
|
||||
// 1. Setup lattice parameters
|
||||
n := 4096 // Polynomial degree
|
||||
q := big.NewInt(0).SetBit(big.NewInt(0), 119, 1) // Prime modulus
|
||||
|
||||
r, err := ring.NewRing(n, q)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 2. Setup samplers
|
||||
prng, _ := sampling.NewKeyedPRNG([]byte("seed"))
|
||||
uniformSampler := ring.NewUniformSampler(prng, r)
|
||||
gaussianSampler := ring.NewGaussianSampler(
|
||||
prng, r,
|
||||
ring.DiscreteGaussian{Sigma: 3.2},
|
||||
false,
|
||||
)
|
||||
|
||||
// 3. Generate lattice-based keys
|
||||
ringSize := 8 // Smaller ring due to larger signatures
|
||||
|
||||
publicKeys := make([]LatticePublicKey, ringSize)
|
||||
var signerSecret LatticeSecretKey
|
||||
signerIndex := 3
|
||||
|
||||
for i := 0; i < ringSize; i++ {
|
||||
pk, sk := generateLatticeKeyPair(r, uniformSampler, gaussianSampler)
|
||||
publicKeys[i] = pk
|
||||
|
||||
if i == signerIndex {
|
||||
signerSecret = sk
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Create lattice ring signature
|
||||
message := []byte("Post-quantum secure message")
|
||||
|
||||
sig := createLatticeRingSignature(
|
||||
r,
|
||||
message,
|
||||
publicKeys,
|
||||
signerIndex,
|
||||
signerSecret,
|
||||
)
|
||||
|
||||
// 5. Verify signature
|
||||
valid := verifyLatticeRingSignature(r, message, sig, publicKeys)
|
||||
fmt.Printf("Lattice ring signature valid: %v\n", valid)
|
||||
|
||||
// 6. Check signature size
|
||||
sigBytes := sig.Serialize()
|
||||
fmt.Printf("Lattice signature size: %d KB\n", len(sigBytes)/1024)
|
||||
}
|
||||
|
||||
type LatticePublicKey struct {
|
||||
A structs.Matrix[ring.Poly]
|
||||
B structs.Vector[ring.Poly]
|
||||
}
|
||||
|
||||
type LatticeSecretKey struct {
|
||||
S structs.Vector[ring.Poly]
|
||||
}
|
||||
|
||||
func generateLatticeKeyPair(
|
||||
r *ring.Ring,
|
||||
uniformSampler *ring.UniformSampler,
|
||||
gaussianSampler *ring.GaussianSampler,
|
||||
) (LatticePublicKey, LatticeSecretKey) {
|
||||
// Generate random matrix A
|
||||
m, n := 8, 8
|
||||
A := utils.SamplePolyMatrix(r, m, n, uniformSampler, true, true)
|
||||
|
||||
// Generate secret vector s
|
||||
s := utils.SamplePolyVector(r, n, gaussianSampler, false, false)
|
||||
|
||||
// Generate error vector e
|
||||
e := utils.SamplePolyVector(r, m, gaussianSampler, false, false)
|
||||
|
||||
// Compute public key b = As + e
|
||||
b := utils.InitializeVector(r, m)
|
||||
utils.MatrixVectorMul(r, A, s, b)
|
||||
utils.VectorAdd(r, b, e, b)
|
||||
|
||||
return LatticePublicKey{A: A, B: b}, LatticeSecretKey{S: s}
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Q-Chain
|
||||
|
||||
### Using Corona in QuantumVM
|
||||
|
||||
```go
|
||||
// Smart contract using ring signatures
|
||||
contract PrivacyPool {
|
||||
mapping(bytes32 => bool) public keyImages;
|
||||
uint256 public poolBalance;
|
||||
|
||||
event Deposit(bytes32 commitment);
|
||||
event Withdrawal(bytes32 keyImage);
|
||||
|
||||
function deposit() external payable {
|
||||
require(msg.value > 0, "Invalid amount");
|
||||
|
||||
// Generate commitment for depositor
|
||||
bytes32 commitment = keccak256(
|
||||
abi.encodePacked(msg.sender, msg.value, block.timestamp)
|
||||
);
|
||||
|
||||
poolBalance += msg.value;
|
||||
emit Deposit(commitment);
|
||||
}
|
||||
|
||||
function withdrawWithRingSignature(
|
||||
uint256 amount,
|
||||
bytes memory ringSignature,
|
||||
bytes32[] memory ringCommitments
|
||||
) external {
|
||||
// 1. Verify ring signature
|
||||
require(
|
||||
verifyRingSignature(
|
||||
abi.encode(amount, msg.sender),
|
||||
ringSignature,
|
||||
ringCommitments
|
||||
),
|
||||
"Invalid ring signature"
|
||||
);
|
||||
|
||||
// 2. Extract and check key image
|
||||
bytes32 keyImage = extractKeyImage(ringSignature);
|
||||
require(!keyImages[keyImage], "Double spending");
|
||||
|
||||
// 3. Mark key image as used
|
||||
keyImages[keyImage] = true;
|
||||
|
||||
// 4. Transfer funds
|
||||
require(poolBalance >= amount, "Insufficient pool balance");
|
||||
poolBalance -= amount;
|
||||
|
||||
payable(msg.sender).transfer(amount);
|
||||
emit Withdrawal(keyImage);
|
||||
}
|
||||
|
||||
function verifyRingSignature(
|
||||
bytes memory message,
|
||||
bytes memory signature,
|
||||
bytes32[] memory ring
|
||||
) internal pure returns (bool) {
|
||||
// Call Corona precompile for verification
|
||||
return ICoronaVerifier(CORONA_PRECOMPILE).verify(
|
||||
message,
|
||||
signature,
|
||||
ring
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
### Benchmark Different Configurations
|
||||
|
||||
```go
|
||||
func runBenchmarks() {
|
||||
configs := []struct {
|
||||
name string
|
||||
ringSize int
|
||||
algorithm string
|
||||
}{
|
||||
{"Small Ring (8)", 8, "schnorr"},
|
||||
{"Medium Ring (16)", 16, "schnorr"},
|
||||
{"Large Ring (32)", 32, "schnorr"},
|
||||
{"Lattice Small (4)", 4, "lattice"},
|
||||
{"Lattice Medium (8)", 8, "lattice"},
|
||||
{"Hybrid (16)", 16, "hybrid"},
|
||||
}
|
||||
|
||||
for _, cfg := range configs {
|
||||
fmt.Printf("\n=== %s ===\n", cfg.name)
|
||||
|
||||
// Setup
|
||||
ring := generateRing(cfg.ringSize)
|
||||
message := []byte("benchmark message")
|
||||
|
||||
// Measure signing time
|
||||
start := time.Now()
|
||||
sig := sign(message, ring, cfg.algorithm)
|
||||
signTime := time.Since(start)
|
||||
|
||||
// Measure verification time
|
||||
start = time.Now()
|
||||
verify(message, sig, cfg.algorithm)
|
||||
verifyTime := time.Since(start)
|
||||
|
||||
// Measure signature size
|
||||
sigSize := len(sig.Serialize())
|
||||
|
||||
fmt.Printf("Sign time: %v\n", signTime)
|
||||
fmt.Printf("Verify time: %v\n", verifyTime)
|
||||
fmt.Printf("Signature size: %d bytes\n", sigSize)
|
||||
fmt.Printf("Size per ring member: %d bytes\n", sigSize/cfg.ringSize)
|
||||
}
|
||||
}
|
||||
|
||||
// Expected output:
|
||||
// === Small Ring (8) ===
|
||||
// Sign time: 1.2ms
|
||||
// Verify time: 0.9ms
|
||||
// Signature size: 288 bytes
|
||||
// Size per ring member: 36 bytes
|
||||
//
|
||||
// === Medium Ring (16) ===
|
||||
// Sign time: 2.1ms
|
||||
// Verify time: 1.8ms
|
||||
// Signature size: 544 bytes
|
||||
// Size per ring member: 34 bytes
|
||||
//
|
||||
// === Large Ring (32) ===
|
||||
// Sign time: 4.2ms
|
||||
// Verify time: 3.5ms
|
||||
// Signature size: 1056 bytes
|
||||
// Size per ring member: 33 bytes
|
||||
//
|
||||
// === Lattice Small (4) ===
|
||||
// Sign time: 3.5ms
|
||||
// Verify time: 2.1ms
|
||||
// Signature size: 8192 bytes
|
||||
// Size per ring member: 2048 bytes
|
||||
//
|
||||
// === Hybrid (16) ===
|
||||
// Sign time: 5.3ms
|
||||
// Verify time: 3.9ms
|
||||
// Signature size: 8704 bytes
|
||||
// Size per ring member: 544 bytes
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Comprehensive Error Handling
|
||||
|
||||
```go
|
||||
func robustRingSignature() error {
|
||||
// 1. Validate inputs
|
||||
if len(ring) < MinRingSize {
|
||||
return fmt.Errorf("ring too small: got %d, need at least %d",
|
||||
len(ring), MinRingSize)
|
||||
}
|
||||
|
||||
if signerIndex >= len(ring) {
|
||||
return fmt.Errorf("signer index out of bounds: %d >= %d",
|
||||
signerIndex, len(ring))
|
||||
}
|
||||
|
||||
// 2. Check for duplicate keys in ring
|
||||
seen := make(map[string]bool)
|
||||
for i, pk := range ring {
|
||||
key := pk.String()
|
||||
if seen[key] {
|
||||
return fmt.Errorf("duplicate key at index %d", i)
|
||||
}
|
||||
seen[key] = true
|
||||
}
|
||||
|
||||
// 3. Validate private key corresponds to public key
|
||||
derivedPub := DerivePublicKey(privKey)
|
||||
if !derivedPub.Equal(ring[signerIndex]) {
|
||||
return errors.New("private key doesn't match public key in ring")
|
||||
}
|
||||
|
||||
// 4. Sign with timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
sigChan := make(chan *RingSignature)
|
||||
errChan := make(chan error)
|
||||
|
||||
go func() {
|
||||
sig, err := SignRingWithContext(ctx, message, ring, signerIndex, privKey)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
} else {
|
||||
sigChan <- sig
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case sig := <-sigChan:
|
||||
// 5. Verify signature before returning
|
||||
if !VerifyRing(message, sig) {
|
||||
return errors.New("generated signature failed verification")
|
||||
}
|
||||
return nil
|
||||
|
||||
case err := <-errChan:
|
||||
return fmt.Errorf("signing failed: %w", err)
|
||||
|
||||
case <-ctx.Done():
|
||||
return errors.New("signing timeout exceeded")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Utilities
|
||||
|
||||
### Test Helper Functions
|
||||
|
||||
```go
|
||||
// Generate test ring with known keys
|
||||
func generateTestRing(size int) (*TestRing, error) {
|
||||
tr := &TestRing{
|
||||
Size: size,
|
||||
PublicKeys: make([]*PublicKey, size),
|
||||
PrivateKeys: make([]*PrivateKey, size),
|
||||
}
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
pub, priv, err := GenerateKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tr.PublicKeys[i] = pub
|
||||
tr.PrivateKeys[i] = priv
|
||||
}
|
||||
|
||||
return tr, nil
|
||||
}
|
||||
|
||||
// Test double-spending detection
|
||||
func testDoubleSpending(t *testing.T) {
|
||||
ring, _ := generateTestRing(16)
|
||||
message1 := []byte("first transaction")
|
||||
message2 := []byte("second transaction")
|
||||
|
||||
// Sign two different messages with same key
|
||||
sig1, _ := SignRing(message1, ring.PublicKeys, 0, ring.PrivateKeys[0])
|
||||
sig2, _ := SignRing(message2, ring.PublicKeys, 0, ring.PrivateKeys[0])
|
||||
|
||||
// Key images should be identical (linkable)
|
||||
if !sig1.KeyImage.Equal(sig2.KeyImage) {
|
||||
t.Error("Key images should be identical for same signer")
|
||||
}
|
||||
|
||||
// Create double-spend detector
|
||||
detector := NewDoubleSpendDetector()
|
||||
|
||||
// First signature should be accepted
|
||||
if !detector.Add(sig1.KeyImage) {
|
||||
t.Error("First signature should be accepted")
|
||||
}
|
||||
|
||||
// Second signature should be rejected (double-spend)
|
||||
if detector.Add(sig2.KeyImage) {
|
||||
t.Error("Second signature should be rejected as double-spend")
|
||||
}
|
||||
}
|
||||
|
||||
type DoubleSpendDetector struct {
|
||||
keyImages map[string]bool
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func NewDoubleSpendDetector() *DoubleSpendDetector {
|
||||
return &DoubleSpendDetector{
|
||||
keyImages: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DoubleSpendDetector) Add(ki *KeyImage) bool {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
key := ki.String()
|
||||
if d.keyImages[key] {
|
||||
return false // Already seen
|
||||
}
|
||||
|
||||
d.keyImages[key] = true
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
These examples demonstrate the versatility and power of Corona for privacy-preserving applications. From simple ring signatures to complex threshold protocols and post-quantum implementations, Corona provides the tools needed for strong privacy guarantees in blockchain and cryptographic applications.
|
||||
@@ -1,18 +0,0 @@
|
||||
import { docs } from "@/.source"
|
||||
import { loader } from "fumadocs-core/source"
|
||||
|
||||
// Create a single source instance that is reused
|
||||
// This prevents circular references and stack overflow issues
|
||||
let _source: ReturnType<typeof loader> | null = null
|
||||
|
||||
export function getSource() {
|
||||
if (!_source) {
|
||||
_source = loader({
|
||||
baseUrl: "/docs",
|
||||
source: docs.toFumadocsSource(),
|
||||
})
|
||||
}
|
||||
return _source
|
||||
}
|
||||
|
||||
export const source = getSource()
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { MDXComponents } from "mdx/types"
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx"
|
||||
|
||||
export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
return {
|
||||
...defaultMdxComponents,
|
||||
...components,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
# Corona — TEE Integration (proposed)
|
||||
|
||||
> Companion to `DEPLOYMENT-RUNBOOK.md §Operational mitigations item 5`
|
||||
> ("TEE attestation, recommended"). This document specifies the
|
||||
> attestation boundary, key-isolation contract, and the per-platform
|
||||
> integration shape — without complecting any of this with the
|
||||
> Corona cryptographic core.
|
||||
|
||||
**Decomplecting rule (load-bearing).** TEE attestation is a single
|
||||
*layer* sitting outside the cryptographic math:
|
||||
|
||||
```
|
||||
+--------------------------------------------------------------+
|
||||
| operator policy: which TEE? which key-release predicate? | policy
|
||||
+--------------------------------------------------------------+
|
||||
| attestation: evidence -> verifier -> bool | trust
|
||||
+--------------------------------------------------------------+
|
||||
| share storage / signing: sealed share -> Round1/Round2/Final | crypto
|
||||
+--------------------------------------------------------------+
|
||||
| Corona kernel: 2-round R-LWE signing | math
|
||||
+--------------------------------------------------------------+
|
||||
```
|
||||
|
||||
The Corona kernel (`sign/`, `threshold/`, `dkg2/`, `reshare/`) MUST
|
||||
NOT depend on, link against, or branch on TEE state. The TEE layer
|
||||
is **only** consulted at three lifecycle moments:
|
||||
|
||||
1. **Bootstrap-trusted-dealer ceremony**: caller of
|
||||
`keyera.BootstrapTrustedDealer` decides whether to run inside a
|
||||
TEE. Corona observes the result via the standard
|
||||
`BootstrapTranscript` — no API change.
|
||||
2. **Per-validator share storage**: each validator's `KeyShare`
|
||||
bytes are sealed under a TEE-bound key. Corona observes the
|
||||
share via the standard `KeyShare` struct — no API change.
|
||||
3. **Per-validator signing session**: `Round1`, `Round2`, and
|
||||
`Finalize` execute inside the TEE. Corona observes the signing
|
||||
protocol via the standard `(D, MACs)`, `Z`, `Signature` byte
|
||||
structures — no API change.
|
||||
|
||||
There is no `corona.AttestationVerifier` interface, no
|
||||
`corona.WithTEE(...)` option, no TEE-specific build tag. The
|
||||
TEE layer is an *operator's deployment concern* and is wired
|
||||
above Corona via the consensus layer's validator-bootstrap
|
||||
plumbing.
|
||||
|
||||
---
|
||||
|
||||
## §1 Threat model addition
|
||||
|
||||
In `docs/mptc/threat-model.md §9.2 "Out of scope at this submission"`,
|
||||
the following items are flagged as **deployment-layer-mitigated** via
|
||||
TEE:
|
||||
|
||||
- Cache-timing side channels
|
||||
- Power side channels
|
||||
- EM side channels
|
||||
- Aggregator-host compromise during signing session
|
||||
(`DEPLOYMENT-RUNBOOK.md §Trust-model disclosure item 2`)
|
||||
|
||||
The TEE integration layer brings these from "not addressed" to
|
||||
"addressed under the TCB of {SGX, SEV-SNP, TDX, NVIDIA-CC, Apple-SEP}",
|
||||
with the following residual assumption surface:
|
||||
|
||||
| Assumption | What we trust |
|
||||
|---|---|
|
||||
| TEE vendor firmware | The CPU/GPU vendor's microcode, BIOS, and signed bootloader. |
|
||||
| TEE attestation root | The vendor's attestation signing key (Intel IAS, AMD KDS, NVIDIA NRAS, Apple AAS). |
|
||||
| Reproducible build | The `luxfi/corona` binary measured into the attestation report matches a publicly-published Git SHA at a tagged release. |
|
||||
| TEE side-channel resistance | The TEE's own side-channel posture — bounded by the public CVE record of the chosen platform (e.g., SGX has a long history of micro-architectural side-channel attacks; SEV-SNP and TDX are more recent). |
|
||||
|
||||
The TEE layer trades a TCB inclusion (vendor microcode + attestation
|
||||
root) for closure of the OS-kernel-compromise and side-channel
|
||||
threats. Operators MUST evaluate whether this trade is acceptable
|
||||
for their specific deployment.
|
||||
|
||||
## §2 Reproducible build contract
|
||||
|
||||
Every Corona release tag (`v0.7.x`) ships:
|
||||
|
||||
1. **Source SHA**: the Git SHA of the release commit.
|
||||
2. **`scripts/build.sh` invocation**: produces the binary
|
||||
`bin/corona` from the release commit.
|
||||
3. **Reference-measure manifest**: SHA-256 of `bin/corona` produced
|
||||
on a pinned builder (`golang:1.26.3-alpine` per `Dockerfile`).
|
||||
4. **Cross-runtime byte-equality**: `scripts/regen-kats.sh --verify`
|
||||
against the C++ port at `~/work/luxcpp/crypto/corona/`.
|
||||
|
||||
The TEE attestation verifier consumes (1) + (3) and rejects any
|
||||
report whose measurement does not match the published manifest. The
|
||||
manifest is published at `https://lux.network/release/corona/v0.7.x/manifest.json`
|
||||
and signed by the foundation release key.
|
||||
|
||||
> **Roadmap (v0.7.6)**: pin the `golang:1.26.3-alpine` builder image
|
||||
> by digest, not tag, so the reference measure is reproducible
|
||||
> against a specific OCI image digest.
|
||||
|
||||
## §3 Per-platform integration
|
||||
|
||||
### §3.1 AMD SEV-SNP (Linux validators)
|
||||
|
||||
**Status**: recommended primary path for Linux validators.
|
||||
|
||||
**Boundary**: full VM-level confidentiality. The Corona validator
|
||||
process runs inside a SEV-SNP-protected VM ("CVM"). The
|
||||
hypervisor sees encrypted memory; the host kernel cannot read
|
||||
guest pages.
|
||||
|
||||
**Attestation flow**:
|
||||
|
||||
1. CVM boot loads OVMF -> Linux kernel -> `cosi-cvm-agent` (the
|
||||
Lux CVM bootstrap agent; lives in `~/work/lux/cosi-cvm-agent`).
|
||||
2. Agent calls `SNP_GET_REPORT` ioctl to obtain a SEV-SNP
|
||||
attestation report binding the in-memory `(measurement,
|
||||
report_data)`. `report_data` is the SHA-256 of the
|
||||
validator-bound `report_nonce` (received from the registration
|
||||
service on first contact).
|
||||
3. Agent posts the report to the consensus layer's TEE-registration
|
||||
endpoint. The endpoint verifies the report against AMD's KDS
|
||||
(Key Distribution Service) using the chip's VCEK certificate,
|
||||
confirms `measurement` matches the published `bin/corona`
|
||||
manifest, and accepts the validator.
|
||||
4. On accept, the consensus layer releases the validator's
|
||||
pre-sealed `KeyShare` (encrypted under a key derived from the
|
||||
attestation transcript) to the agent.
|
||||
5. Agent unseals into the SEV-SNP-protected memory; Corona's
|
||||
`threshold.NewSigner` operates on the unsealed share.
|
||||
|
||||
**Key isolation**: the SEV-SNP VM memory is encrypted by the
|
||||
PSP-bound C-bit memory encryption. The unsealed share is never
|
||||
visible to the hypervisor or the host kernel.
|
||||
|
||||
**Side channels addressed**: cold-boot, DMA-based read of guest
|
||||
memory, hypervisor-introspection, and (under SEV-SNP integrity
|
||||
protection, not SEV-ES) RowHammer and Spectre-class transient
|
||||
attacks from the host.
|
||||
|
||||
**Residual risks**: SEV-SNP's own published CVE record (e.g.,
|
||||
CVE-2023-20593 "Zenbleed", CVE-2024-3315 "SmmCallout"). Operators
|
||||
MUST apply microcode patches.
|
||||
|
||||
**Code touchpoint**: zero. Corona's `KeyShare` bytes are unsealed
|
||||
by the agent and handed to `threshold.NewSigner` via the standard
|
||||
Go struct.
|
||||
|
||||
### §3.2 NVIDIA Confidential Computing (H100/H200/B200 CC mode)
|
||||
|
||||
**Status**: recommended when GPU-accelerated NTT/Montgomery is
|
||||
used in production. Corona's `gpu` package opts the lattice NTT
|
||||
dispatch into the GPU at validator setup time; the GPU itself
|
||||
becomes part of the validator's TCB. **Confidential Computing**
|
||||
mode on H100/H200/B200 puts the GPU into an attestable
|
||||
confidential mode where the host CPU cannot read GPU memory.
|
||||
|
||||
**Boundary**: a CVM (SEV-SNP or TDX) is paired with a CC-mode
|
||||
GPU. The PCIe link is encrypted via SPDM (Security Protocol and
|
||||
Data Model) session keys. The GPU's HBM memory is protected by
|
||||
the GPU's own confidential-mode firmware.
|
||||
|
||||
**Attestation flow**:
|
||||
|
||||
1. CVM boot (per §3.1 or §3.3).
|
||||
2. CVM-to-GPU SPDM session is established. The GPU produces a
|
||||
**device attestation report** signed by the NRAS (NVIDIA Remote
|
||||
Attestation Service) root.
|
||||
3. Agent verifies the GPU report via NRAS, confirms the GPU
|
||||
firmware version + CC-mode active.
|
||||
4. Composite attestation: agent emits `evidence = SNP_report ||
|
||||
NRAS_GPU_report || binding_nonce`. The consensus-layer verifier
|
||||
checks both reports and the binding.
|
||||
5. Corona's `gpu.UseAccelerator()` is called inside the CVM after
|
||||
composite attestation passes. The lattice GPU NTT dispatch
|
||||
runs over the encrypted PCIe link to the CC-mode GPU.
|
||||
|
||||
**Key isolation**: secret shares never leave the CVM's encrypted
|
||||
memory. The data sent to the GPU for NTT computation is the
|
||||
*coefficient vector after Montgomery encoding* — the secret-share
|
||||
material is mixed in earlier (in CPU code) and the GPU NTT operates
|
||||
on values that are blinded by the per-session mask `R` (Round 1)
|
||||
and the public matrix `A` (Round 2). The GPU sees no clear-text
|
||||
share.
|
||||
|
||||
> **HONEST GAP**: the precise blinding analysis ("what does the GPU
|
||||
> see, formally?") for the CC-mode dispatch is an open
|
||||
> question for the v0.8.0 cryptographic audit. Until that audit
|
||||
> completes, deploying Corona under CC-mode GPU is APPROVED with
|
||||
> the caveat that the GPU is part of the TCB; operators MUST
|
||||
> evaluate whether they trust NVIDIA's CC-mode firmware + NRAS
|
||||
> attestation.
|
||||
|
||||
**Side channels addressed**: PCIe sniffing, host-DMA-into-GPU-memory,
|
||||
GPU-firmware-from-host introspection.
|
||||
|
||||
**Residual risks**: NVIDIA CC-mode CVE record (e.g., GPU-resident
|
||||
side-channels in shared-memory paths — none publicly disclosed as
|
||||
of 2026-06-01, but the platform is recent).
|
||||
|
||||
**Code touchpoint**: zero in `corona/sign`, `corona/threshold`. One
|
||||
plumbing change in `corona/gpu/gpu.go::MaybeRegister` to optionally
|
||||
gate registration on a "confidential-mode-attested" flag passed at
|
||||
context-init time. **Proposed (not yet implemented)**:
|
||||
|
||||
```go
|
||||
// MaybeRegisterAttested is the CC-mode variant of MaybeRegister.
|
||||
// It registers the ring only if the supplied attestation token
|
||||
// passes the consensus-layer's attestation verifier.
|
||||
//
|
||||
// On nil token the call falls through to plain MaybeRegister
|
||||
// (preserves the existing API contract).
|
||||
func MaybeRegisterAttested(r *ring.Ring, attestation []byte) error {
|
||||
if attestation == nil {
|
||||
MaybeRegister(r)
|
||||
return nil
|
||||
}
|
||||
if !attestation_verifier.Verify(attestation) {
|
||||
return ErrAttestationRejected
|
||||
}
|
||||
return RegisterRing(r)
|
||||
}
|
||||
```
|
||||
|
||||
The `attestation_verifier` package would live OUTSIDE `corona/` —
|
||||
in the consensus layer at `~/work/lux/threshold/attestation/` or
|
||||
similar. Corona just consumes the bool.
|
||||
|
||||
### §3.3 Intel TDX (alternative Linux path)
|
||||
|
||||
**Status**: alternative to §3.1 for Intel platforms. Substantively
|
||||
equivalent boundary (VM-level confidentiality, attestation via
|
||||
Intel TDX Provisioning Certification Service).
|
||||
|
||||
**Attestation flow**: analogous to §3.1, replacing `SNP_GET_REPORT`
|
||||
with `TDG.MR.REPORT` and replacing AMD KDS with Intel PCCS / TGS.
|
||||
|
||||
**Composite with NVIDIA CC**: TDX + H100 CC is a supported
|
||||
deployment configuration per NVIDIA's CC documentation.
|
||||
|
||||
### §3.4 Apple Secure Enclave (validator share storage on
|
||||
Apple Silicon)
|
||||
|
||||
**Status**: recommended for Apple Silicon validators where the
|
||||
SEP-bound key is used to seal the at-rest `KeyShare`.
|
||||
|
||||
**Boundary**: the SEP is a separate ARM core inside the M-series
|
||||
SoC with its own bootloader, kernel, and tamper-resistant key
|
||||
storage. SEP-bound keys are non-extractable and gated by
|
||||
SecureEnclave biometric / passcode policy.
|
||||
|
||||
**Attestation flow** (limited compared to SEV-SNP):
|
||||
|
||||
1. Validator process generates a per-validator long-term key
|
||||
via `Security.framework` `SecKeyCreateRandomKey` with
|
||||
`kSecAttrTokenIDSecureEnclave`. The private key never leaves
|
||||
the SEP.
|
||||
2. The KeyShare bytes are wrapped under an AES-256-GCM key whose
|
||||
master key is derived from a `SecKeyCreateRandomKey`-backed
|
||||
ECC P-256 key in the SEP. Decryption requires the SEP to
|
||||
sign a challenge under the SEP-bound private key.
|
||||
3. There is NO ATTESTATION REPORT comparable to SEV-SNP/TDX/CC —
|
||||
Apple does NOT publish a remote-attestation root for the SEP.
|
||||
Validators using SEP-bound storage cannot prove to the chain
|
||||
that their share is SEP-sealed; this is a **local-only**
|
||||
defense-in-depth measure.
|
||||
|
||||
**Key isolation**: at-rest share material is sealed under a
|
||||
non-extractable SEP key. A non-root attacker on the macOS host
|
||||
cannot extract the share without unlocking the SEP via the
|
||||
`LAContext.evaluatePolicy` biometric/passcode flow.
|
||||
|
||||
**Side channels addressed**: cold-boot, disk-image-exfiltration,
|
||||
non-root userland processes reading the validator's share file.
|
||||
|
||||
**NOT addressed**: a root-equivalent attacker on the macOS host
|
||||
who calls `Security.framework` after the SEP unlocks (because
|
||||
SEP unlock policy delegates to the host OS for biometric
|
||||
evaluation). For full host-isolation on Apple Silicon, run the
|
||||
validator inside a `virtio-fs`-backed Linux VM under Apple's
|
||||
`Virtualization.framework` and use the Linux VM's SEV-SNP-style
|
||||
attestation (not available natively; future work).
|
||||
|
||||
**Code touchpoint**: zero in `corona/`. The Apple SEP wrapping
|
||||
lives in `~/work/lux/threshold/storage/sep-darwin.go` (or
|
||||
analogous) at the storage layer. Corona's `KeyShare` is loaded
|
||||
via the storage layer's `LoadShare()` API which returns the
|
||||
unwrapped `KeyShare` struct.
|
||||
|
||||
### §3.5 Intel SGX (deprecated for Corona)
|
||||
|
||||
**Status**: NOT recommended. Intel SGX has a long published CVE
|
||||
record of micro-architectural side-channel attacks (Foreshadow,
|
||||
ZombieLoad, LVI, ÆPIC Leak). Corona's R-LWE arithmetic spends
|
||||
significant time on `lattigo`'s NTT and Gaussian sampling — both
|
||||
data-dependent paths that have been demonstrated vulnerable to
|
||||
side-channel extraction on SGX in the published literature.
|
||||
|
||||
SGX is supported in the *attestation-layer interface* (the
|
||||
consensus-layer verifier accepts SGX EPID/DCAP reports), but the
|
||||
**Corona reference deployment guidance** in
|
||||
`DEPLOYMENT-RUNBOOK.md` explicitly prefers SEV-SNP / TDX / CC-mode
|
||||
over SGX.
|
||||
|
||||
## §4 Composite attestation evidence
|
||||
|
||||
The consensus-layer registration endpoint accepts a single composite
|
||||
attestation evidence bundle for any combination of:
|
||||
|
||||
- **CPU side**: SEV-SNP report OR TDX report OR (SGX report,
|
||||
not recommended).
|
||||
- **GPU side**: NRAS attestation report (optional; required only
|
||||
if `gpu.UseAccelerator()` is invoked).
|
||||
- **Storage side**: SEP-bound key witness (Apple-only;
|
||||
defense-in-depth, no remote-attestation).
|
||||
|
||||
The composite is bound by:
|
||||
|
||||
```
|
||||
binding_nonce = SHA-256( "corona-tee-bind-v1" ||
|
||||
validator_id ||
|
||||
group_id ||
|
||||
era_id ||
|
||||
challenge_nonce )
|
||||
```
|
||||
|
||||
where `challenge_nonce` is fresh per-registration randomness from
|
||||
the consensus layer. Each platform-specific report embeds
|
||||
`binding_nonce` in its `report_data` field. The verifier checks
|
||||
all reports, confirms binding-nonce consistency, and accepts the
|
||||
validator on success.
|
||||
|
||||
## §5 Key release predicate
|
||||
|
||||
The pre-sealed `KeyShare` at the consensus-layer registration
|
||||
service is encrypted under a key derived from the attestation
|
||||
transcript. **The key release predicate** is:
|
||||
|
||||
```
|
||||
release_key = HKDF-SHA-256(
|
||||
salt = "corona-share-release-v1",
|
||||
ikm = composite_attestation_transcript,
|
||||
info = validator_id || group_id || era_id,
|
||||
length = 32,
|
||||
)
|
||||
```
|
||||
|
||||
The consensus-layer registration service computes this key only on
|
||||
successful composite-attestation verification. The registration
|
||||
service then unwraps the validator's `KeyShare` under this key and
|
||||
delivers the wrapped bytes to the attesting validator.
|
||||
|
||||
**This is the policy gate.** Without a passing attestation, no
|
||||
key release. Without a key release, no Round 1 / Round 2 / Final.
|
||||
|
||||
## §6 Honest non-claims
|
||||
|
||||
- Corona does NOT today ship `~/work/lux/threshold/attestation/`.
|
||||
That package is a **proposed** addition for the v0.7.6 / v0.8.0
|
||||
roadmap; this document specifies its API surface.
|
||||
- Corona does NOT today ship `MaybeRegisterAttested` in `gpu/`.
|
||||
Same roadmap.
|
||||
- Apple SEP integration is **local-only** — no remote attestation
|
||||
is possible against Apple's platform. Operators relying on
|
||||
Apple-Silicon validators MUST accept this as a defense-in-depth
|
||||
measure, not a primary trust anchor.
|
||||
- The "what does the CC-mode GPU see, formally?" blinding analysis
|
||||
for §3.2 is an OPEN audit item for v0.8.0.
|
||||
|
||||
## §7 Roadmap
|
||||
|
||||
| Item | Target | Owner |
|
||||
|---|---|---|
|
||||
| `attestation_verifier` package at `~/work/lux/threshold/attestation/` | v0.7.6 | consensus team |
|
||||
| `MaybeRegisterAttested` in `gpu/gpu.go` | v0.7.6 | corona |
|
||||
| SEV-SNP CVM bootstrap agent at `~/work/lux/cosi-cvm-agent` | v0.7.6 | infra |
|
||||
| Reference docker-compose for "validator + SEV-SNP CVM + H100 CC" | v0.8.0 | infra |
|
||||
| Apple SEP storage layer at `~/work/lux/threshold/storage/sep-darwin.go` | v0.8.0 | apple-silicon track |
|
||||
| Formal blinding analysis for CC-mode GPU (NTT inputs/outputs) | v0.8.0 | external audit (GATE-4) |
|
||||
| Reproducible builder image pinned by digest | v0.7.6 | release |
|
||||
|
||||
---
|
||||
|
||||
**Document metadata**
|
||||
|
||||
- Name: `docs/mptc/tee-integration.md`
|
||||
- Version: v0.1 (initial TEE integration spec)
|
||||
- Date: 2026-06-02
|
||||
- Companion to: `DEPLOYMENT-RUNBOOK.md §Operational mitigations item 5`,
|
||||
`docs/mptc/threat-model.md §9.2`
|
||||
- Status: proposed; no Corona code change required for §3.1, §3.3, §3.4.
|
||||
§3.2 adds one optional plumbing function (`MaybeRegisterAttested`)
|
||||
at the next minor version.
|
||||
@@ -1,20 +0,0 @@
|
||||
import { createMDX } from "fumadocs-mdx/next"
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const config = {
|
||||
output: 'export',
|
||||
reactStrictMode: true,
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
experimental: {
|
||||
webpackBuildWorker: true,
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
}
|
||||
|
||||
const withMDX = createMDX()
|
||||
|
||||
export default withMDX(config)
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "@luxfi/corona-docs",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --port 3001",
|
||||
"build": "fumadocs-mdx && TURBOPACK=0 next build",
|
||||
"export": "TURBOPACK=0 next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"fumadocs-core": "^15.8.5",
|
||||
"fumadocs-mdx": "^12.0.3",
|
||||
"fumadocs-ui": "^15.8.5",
|
||||
"lucide-react": "^0.468.0",
|
||||
"next": "16.0.1",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.16",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.49",
|
||||
"rehype-pretty-code": "^0.14.1",
|
||||
"shiki": "^1.27.2",
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"packageManager": "[email protected]"
|
||||
}
|
||||
Generated
-4136
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import {
|
||||
defineConfig,
|
||||
defineDocs,
|
||||
} from "fumadocs-mdx/config"
|
||||
import rehypePrettyCode from "rehype-pretty-code"
|
||||
|
||||
export default defineConfig({
|
||||
mdxOptions: {
|
||||
rehypePlugins: [
|
||||
[
|
||||
rehypePrettyCode,
|
||||
{
|
||||
theme: {
|
||||
dark: "github-dark-dimmed",
|
||||
light: "github-light",
|
||||
},
|
||||
keepBackground: false,
|
||||
defaultLang: "go",
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
export const docs = defineDocs({
|
||||
dir: "content/docs",
|
||||
})
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
},
|
||||
"target": "ES2017"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user