MetaAccess

Introduction

MetaAccess 用于为提供一个去中心化的授权功能,让链上的加密数据,按照特定规则授权查看。

Spec

约定需要两个协议,AccessControl和AccessPass。

  • AccessControl负责设置权限进行控制,在发布密文内容的同时也发布AccessControl上链。

  • AccessPass负责构建付费和授权交易,用于授权展示明文内容

AccessControl

path: /metaaccess/accesscontrol

{
	"publicContent": "public part of content",//公开部分内容
	"publicPins":["PINID-1", "PINID-2"],//公开部分文件
	"publicPath": "/protocols/simplepublicbuzz",
	"controlPins":["PINID1","PINID2"], //Array of PINs that will be in control of accessing
	"controlPath": "/protocols/simpleasseccbuzz",//The pins which is in this path will be in control of accessing
	"manDomain":"",//待定
	"manPubkey":"THE-PUBKEY-OF-MAN", //Pubkey of the MAN node providing custody decryption services.
	"creatorPubkey":"THE-PUBKEY-OF-CREATOR",//Pubkey of the creator
	"encryptedKey":"Use the ECDH Key to Decrypt it and use that decryptedkey to decrypt the content",
	"holdCheck":{//hold检查
		"type":"mrc20" //"chainCoin" or "mrc20", 
		"ticker":"mc" //the ticker of mrc20;if type = chainCoin then it will be ignored
		"amount":"1000"
	},
	"payCheck":{//pay检查
		"type":"chainCoin", //"chainCoin" or "mrc20"
		"ticker":"",
		"amount":"0.00001",
		"payTo":"address",
		"validPeriod": "4320", //blocks,4320 means 1 month
	},
}

AccessPass

path: /metaaccess/accesspass

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

流程

创作者:

  1. 应用端请求MAN获取publicKey,此时MAN会针对该请求生成一对公私钥并保存,然后返回man-publicKey

  2. 应用端对钱包请求ecdh操作,根据传的钱包路径和man-publicKey,生成协商密钥SP

  3. 应用端生成随机AES密钥-P1

  4. 应用端编辑文本或图片,选择公开部分和付费部分,设置付费模式

  5. 使用密钥-P1对付费部分内容进行AES加密,即对整个payload进行加密,得到内容txRaw

  6. 使用协商密钥SP对密钥-P1进行AES加密,得到encrypted-key,构建accesscontrol 的pin

  7. 把内容pin和accesscontrol 的pin统一广播上链

购买者:

  1. 应用端构建accesspass ,output中带有针对accesscontrol所指定的payment

  2. MAN提供获取密文的接口,需要带钱包的头部签名信息,MAN验证签名信息,获取带签名地址的accesspass

  3. MAN根据accessControlID查询对应的accesscontrol ,用man-privateKey与creator-publicKey生成协商密钥SP

  4. MAN先判断accesspass是否符合accesscontrol ,符合进行下一步,不符合则返回空

  5. 用协商密钥SP对encrypted-key解密,获取密钥-P1

  6. MAN用密钥-P1解密对应的controlPins,返回明文内容

ECDH 配置说明

为了确保客户端与服务器端在密钥交换过程中能够正常协作,双方在 ECDH (Elliptic Curve Diffie-Hellman) 密钥交换协议中需要统一以下配置参数:

  • 椭圆曲线类型

    • 使用的曲线:NIST P-256(即 secp256r1prime256v1)。

    • P-256 是一种被广泛使用的椭圆曲线,兼具较好的安全性和效率。

  • 公钥和私钥格式

    • 私钥和公钥均以 Hex 编码 的字符串形式进行传输。

    • 公钥在传输前通过 PublicKey().Bytes() 转换为字节数组,再进行 Hex 编码;私钥同样通过 Bytes() 转换为字节数组再 Hex 编码。

  • 密钥派生

    • 双方各自生成公私钥对后,使用私钥和对方的公钥计算共享密钥。

    • 共享密钥在计算完成后可以直接用于对称加密的密钥材料。

对称加密配置 (AES)

  • 对称加密算法

    • 使用 AES-256-CFB 模式作为对称加密算法。

    • CFB (Cipher Feedback) 模式支持流式加密和解密,适合在共享密钥环境下进行数据加密。

  • AES 密钥生成

    • 采用 256 位(32 字节)的随机字节作为 AES 密钥,生成时通过 rand.Read 随机生成。

    • AES 密钥使用 Hex 编码存储和传输。

  • 初始化向量 (IV)

    • 每次加密操作生成新的 16 字节(AES 块大小)的随机初始化向量(IV)。

    • IV 放在密文的前面一起传输,解密时需要从密文中提取 IV。

Go代码示例:

// 生成 ECDH 密钥对
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
}

// 密钥交换过程
func PerformECDH(privKeyA *ecdh.PrivateKey, pubKeyB *ecdh.PublicKey) ([]byte, error) {
    return privKeyA.ECDH(pubKeyB) // 生成共享密钥
}

// 生成 AES 密钥
func GenerateAESKey() (string, error) {
    key := make([]byte, 32) // AES-256 key
    _, err := rand.Read(key)
    if err != nil {
        return "", err
    }
    return hexEncode(key), nil
}

// AES 加密
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