MetaAccess

Introduction

MetaAccess provides a decentralized authorization mechanism to grant access to encrypted on-chain data based on specific rules.

Spec

Two protocols are required: AccessControl and AccessPass.

  • AccessControl is responsible for setting permissions and control rules. It is published on-chain along with the encrypted content.

  • AccessPass facilitates payment and authorization transactions, enabling access to decrypted content.

AccessControl

Path: /metaaccess/accesscontrol

{
    "publicContent": "public part of content", // Public portion of the content
    "publicPins": ["PINID-1", "PINID-2"], // Public files
    "publicPath": "/protocols/simplepublicbuzz",
    "controlPins": ["PINID1", "PINID2"], // Array of PINs that require access control
    "controlPath": "/protocols/simpleasseccbuzz", // Path controlling access to the specified PINs
    "manDomain": "", // To be defined
    "manPubkey": "THE-PUBKEY-OF-MAN", // Public key of the MAN node providing decryption services
    "creatorPubkey": "THE-PUBKEY-OF-CREATOR", // Creator's public key
    "encryptedKey": "Use the ECDH Key to Decrypt it and use that decrypted key to decrypt the content",
    "holdCheck": { // Hold check
        "type": "mrc20", // "chainCoin" or "mrc20"
        "ticker": "mc", // Ticker for mrc20; ignored if type is "chainCoin"
        "amount": "1000"
    },
    "payCheck": { // Pay check
        "type": "chainCoin", // "chainCoin" or "mrc20"
        "ticker": "",
        "amount": "0.00001",
        "payTo": "address",
        "validPeriod": "4320" // Blocks; 4320 represents 1 month
    }
}

AccessPass

Path: /metaaccess/accesspass

{
    "accessControlID": "the-pinid-of-accesscontrol-file"
}

Workflow

Creator:

  1. The application requests MAN to generate a public key. MAN generates and stores a key pair, returning the public key (man-publicKey).

  2. The application requests the wallet to perform an ECDH operation using the wallet path and man-publicKey to derive a shared secret (SP).

  3. The application generates a random AES key (P1).

  4. The application edits the text or image, selects the public and paid sections, and sets the payment mode.

  5. Using key P1, the application encrypts the paid content via AES, producing txRaw.

  6. Using the shared secret SP, the application encrypts key P1 to generate encrypted-key and constructs the accesscontrol PIN.

  7. Both the content PIN and accesscontrol PIN are broadcast on-chain.

Buyer:

  1. The application constructs an accesspass with an output containing the payment required by the accesscontrol.

  2. MAN provides an interface to retrieve encrypted content, requiring a wallet-signed header. MAN verifies the signature and retrieves the signed address from the accesspass.

  3. MAN queries the accesscontrol file corresponding to the accessControlID and derives the shared secret (SP) using its private key and the creator's public key.

  4. MAN validates the accesspass against the accesscontrol rules. If valid, it proceeds; otherwise, it returns nothing.

  5. MAN decrypts the encrypted-key using SP to obtain key P1.

  6. MAN uses key P1 to decrypt the corresponding controlPins and returns the decrypted content.

ECDH Configuration

To ensure proper collaboration between client and server during key exchange, both parties must standardize the following parameters in the ECDH (Elliptic Curve Diffie-Hellman) protocol:

  • Elliptic Curve Type

    • Curve: NIST P-256 (aka secp256r1 or prime256v1).

    • P-256 provides a balance of security and efficiency.

  • Public and Private Key Format

    • Keys are transmitted as Hex-encoded strings.

    • Public keys are converted to byte arrays using PublicKey().Bytes() before Hex encoding; the same applies to private keys.

  • Key Derivation

    • Each party generates a public-private key pair, then calculates a shared secret using their private key and the other party's public key.

    • The derived shared secret is directly usable as the symmetric encryption key.

Symmetric Encryption Configuration (AES)

  • Algorithm

    • AES-256-CFB is used for symmetric encryption.

    • The CFB (Cipher Feedback) mode supports streaming encryption and decryption, ideal for shared key environments.

  • Key Generation

    • A 256-bit (32-byte) random key is generated using rand.Read.

    • Keys are stored and transmitted in Hex-encoded form.

  • Initialization Vector (IV)

    • A new 16-byte random IV (AES block size) is generated for each encryption.

    • The IV is prepended to the ciphertext during transmission for decryption purposes.

Go Code Example

// Generate ECDH Key Pair
func GenKeyPair() (privateKey string, publicKey string, e error) {
    curve := ecdh.P256()
    privKeyA, err := curve.GenerateKey(rand.Reader)
    if err != nil {
        return
    }
    privateKey = hex.EncodeToString(privKeyA.Bytes())
    publicKey = hex.EncodeToString(privKeyA.PublicKey().Bytes())
    return
}

// Key Exchange
func PerformECDH(privKeyA *ecdh.PrivateKey, pubKeyB *ecdh.PublicKey) ([]byte, error) {
    return privKeyA.ECDH(pubKeyB) // Generate shared secret
}

// Generate AES Key
func GenerateAESKey() (string, error) {
    key := make([]byte, 32) // AES-256 key
    _, err := rand.Read(key)
    if err != nil {
        return "", err
    }
    return hex.EncodeToString(key), nil
}

// AES Encryption
func EncryptPayloadAES(key, payload []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    ciphertext := make([]byte, aes.BlockSize+len(payload))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return nil, err
    }
    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], payload)
    return ciphertext, nil
}

Last updated