Source Code

;; key-management - Clarity 4
;; Cryptographic key lifecycle management

(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-KEY-NOT-FOUND (err u101))
(define-constant ERR-KEY-EXPIRED (err u102))
(define-constant ERR-KEY-REVOKED (err u103))
(define-constant ERR-INVALID-KEY (err u104))

(define-map encryption-keys (buff 64)
  {
    owner: principal,
    key-type: (string-ascii 20),
    algorithm: (string-ascii 50),
    created-at: uint,
    expires-at: uint,
    is-active: bool,
    rotation-count: uint
  }
)

(define-map key-permissions { key-hash: (buff 64), grantee: principal }
  {
    permission-level: (string-ascii 20),
    granted-at: uint,
    expires-at: uint
  }
)

(define-map key-rotation-history uint
  {
    old-key-hash: (buff 64),
    new-key-hash: (buff 64),
    rotated-by: principal,
    rotated-at: uint,
    reason: (string-utf8 200)
  }
)

(define-map key-escrow (buff 64)
  {
    escrow-holder: principal,
    recovery-threshold: uint,
    shard-count: uint,
    created-at: uint
  }
)

(define-data-var rotation-counter uint u0)
(define-data-var default-key-lifetime uint u31536000) ;; 1 year

;; Register encryption key
(define-public (register-key
    (key-hash (buff 64))
    (key-type (string-ascii 20))
    (algorithm (string-ascii 50))
    (lifetime uint))
  (begin
    (asserts! (is-none (map-get? encryption-keys key-hash)) ERR-INVALID-KEY)
    (ok (map-set encryption-keys key-hash
      {
        owner: tx-sender,
        key-type: key-type,
        algorithm: algorithm,
        created-at: stacks-block-time,
        expires-at: (+ stacks-block-time lifetime),
        is-active: true,
        rotation-count: u0
      }))))

;; Rotate key
(define-public (rotate-key
    (old-key-hash (buff 64))
    (new-key-hash (buff 64))
    (reason (string-utf8 200)))
  (let ((old-key (unwrap! (map-get? encryption-keys old-key-hash) ERR-KEY-NOT-FOUND))
        (rotation-id (+ (var-get rotation-counter) u1)))
    (asserts! (is-eq tx-sender (get owner old-key)) ERR-NOT-AUTHORIZED)
    (map-set encryption-keys old-key-hash (merge old-key { is-active: false }))
    (map-set encryption-keys new-key-hash
      {
        owner: tx-sender,
        key-type: (get key-type old-key),
        algorithm: (get algorithm old-key),
        created-at: stacks-block-time,
        expires-at: (+ stacks-block-time (var-get default-key-lifetime)),
        is-active: true,
        rotation-count: (+ (get rotation-count old-key) u1)
      })
    (map-set key-rotation-history rotation-id
      {
        old-key-hash: old-key-hash,
        new-key-hash: new-key-hash,
        rotated-by: tx-sender,
        rotated-at: stacks-block-time,
        reason: reason
      })
    (var-set rotation-counter rotation-id)
    (ok rotation-id)))

;; Grant key permission
(define-public (grant-key-permission
    (key-hash (buff 64))
    (grantee principal)
    (permission-level (string-ascii 20))
    (duration uint))
  (let ((key (unwrap! (map-get? encryption-keys key-hash) ERR-KEY-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get owner key)) ERR-NOT-AUTHORIZED)
    (ok (map-set key-permissions { key-hash: key-hash, grantee: grantee }
      {
        permission-level: permission-level,
        granted-at: stacks-block-time,
        expires-at: (+ stacks-block-time duration)
      }))))

;; Revoke key
(define-public (revoke-key (key-hash (buff 64)))
  (let ((key (unwrap! (map-get? encryption-keys key-hash) ERR-KEY-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get owner key)) ERR-NOT-AUTHORIZED)
    (ok (map-set encryption-keys key-hash (merge key { is-active: false })))))

;; Setup key escrow
(define-public (setup-escrow
    (key-hash (buff 64))
    (escrow-holder principal)
    (recovery-threshold uint)
    (shard-count uint))
  (let ((key (unwrap! (map-get? encryption-keys key-hash) ERR-KEY-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get owner key)) ERR-NOT-AUTHORIZED)
    (ok (map-set key-escrow key-hash
      {
        escrow-holder: escrow-holder,
        recovery-threshold: recovery-threshold,
        shard-count: shard-count,
        created-at: stacks-block-time
      }))))

;; Read-only functions
(define-read-only (get-key-info (key-hash (buff 64)))
  (ok (map-get? encryption-keys key-hash)))

(define-read-only (get-key-permission (key-hash (buff 64)) (grantee principal))
  (ok (map-get? key-permissions { key-hash: key-hash, grantee: grantee })))

(define-read-only (get-rotation-history (rotation-id uint))
  (ok (map-get? key-rotation-history rotation-id)))

(define-read-only (get-escrow-info (key-hash (buff 64)))
  (ok (map-get? key-escrow key-hash)))

(define-read-only (is-key-valid (key-hash (buff 64)))
  (match (map-get? encryption-keys key-hash)
    key (ok (and (get is-active key) (< stacks-block-time (get expires-at key))))
    (ok false)))

(define-read-only (get-total-rotations)
  (ok (var-get rotation-counter)))

;; Clarity 4: principal-destruct?
(define-read-only (validate-owner (owner principal))
  (principal-destruct? owner))

;; Clarity 4: int-to-ascii
(define-read-only (format-rotation-id (rotation-id uint))
  (ok (int-to-ascii rotation-id)))

;; Clarity 4: string-to-uint?
(define-read-only (parse-rotation-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

;; Clarity 4: burn-block-height
(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (15)

FunctionAccessArgs
register-keypublickey-hash: (buff 64
rotate-keypublicold-key-hash: (buff 64
grant-key-permissionpublickey-hash: (buff 64
revoke-keypublickey-hash: (buff 64
setup-escrowpublickey-hash: (buff 64
get-key-inforead-onlykey-hash: (buff 64
get-key-permissionread-onlykey-hash: (buff 64
get-rotation-historyread-onlyrotation-id: uint
get-escrow-inforead-onlykey-hash: (buff 64
is-key-validread-onlykey-hash: (buff 64
get-total-rotationsread-only
validate-ownerread-onlyowner: principal
format-rotation-idread-onlyrotation-id: uint
parse-rotation-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only