genkey
generateAppKey.js
const SEA = require( 'gun/sea' ) ; // 生成密钥对
SEA.pair( ) .then(( pair) = > { // 输出提示信息console.log( 'This is your secret app key pair.\n Add this to your .dotenv file:' ) ; // 将生成的密钥对转换为 JSON 格式并输出console.log( ` APP_KEY_PAIR = '${JSON.stringify(pair)} ' ` ) ;
} ) ;
$ node ./generateAppKey.js
Hello wonderful person! : ) Thanks for using GUN, please ask for help on http://chat.gun.eco if anything takes you longer than 5min to figure out!
This is your secret app key pair.
Add this to your .dotenv file:
APP_KEY_PAIR = '{"pub":"B14-m6S3i1cgm9bJCsED0FsGbHiDlXJAiKK2OnrPSj0.axmMDTmbdAfU3SjJhgqOn6mH6jDUoazcQ_vHljstyuE","priv":"21kawgH1yBwDLSf4yh63A_AdAja4hh-Q5h_ob_LF-VE","epub":"Z-IWo4zkzXyEL5hWCmvQLY8aoxupbZmJZmKFMDhNJ0U.hoNigMrVpc2npPR17tjOyZchJKk1D8wlQKPCIKZNF_w","epriv":"UUO2sHWG1lrQLNr0t9ObSEHyiasCc_D2HdJS-Vw2FmI"}'
Done in 0 .77s.
APP_KEY_PAIR
APP_KEY_PAIR='{"pub":"B14...","priv":"21k...","epub":"Z-I...","epriv":"UUO..."}'
总结
密钥类型功能对比表
密钥类型 作用 使用场景 是否公开 说明 pub
身份验证、消息签名验证 用于验证签名和公开身份 可以公开 用于确认数据是否由密钥对的拥有者签名。 priv
消息签名 签署消息、身份认证 不可公开 pub
的配对私钥,用于对消息签名;一旦泄露可能导致身份伪造。epub
数据加密、公钥加密 安全数据传输、密钥交换 可以公开 用于加密数据,与 epriv
配对;确保对称密钥安全共享。 epriv
数据解密 解密接收到的加密数据 不可公开 epub
的配对私钥,用于解密加密的数据;必须严格保密。
使用示例
epub
/ epriv
用于 数据加密 和 解密 。假设已经在 .env
文件中保存了密钥对:
APP_KEY_PAIR='{"pub":"B14...","priv":"21k...","epub":"Z-I...","epriv":"UUO..."}'
const SEA = require ( 'gun/sea' ) ;
const pair = JSON . parse ( process. env. APP_KEY_PAIR ) ;
async function encryptMessage ( message, recipientEpub ) { const encrypted = await SEA . encrypt ( message, recipientEpub) ; return encrypted;
}
async function decryptMessage ( encryptedMessage ) { const decrypted = await SEA . decrypt ( encryptedMessage, pair. epriv) ; return decrypted;
}
const recipientEpub = 'Z-IWo4zkzXyEL5hWCmvQLY8aoxupbZmJZmKFMDhNJ0U.hoNigMrVpc2npPR17tjOyZchJKk1D8wlQKPCIKZNF_w' ;
const message = 'Hello, secure world!' ;
encryptMessage ( message, recipientEpub) . then ( ( encrypted ) => { console. log ( 'Encrypted Message:' , encrypted) ; decryptMessage ( encrypted) . then ( ( decrypted ) => { console. log ( 'Decrypted Message:' , decrypted) ; } ) ;
} ) ;
server
启动服务 :通过 Express 和 GUN 创建服务器。GUN 实例配置 : 验证所有进入的 GUN 消息是否带有有效的 JWT。 自动将应用本身认证为 GUN 用户,使其可以管理数据。 API 路由 : /api/certificates
:允许用户获取证书,以限制其对特定数据路径的访问。/api/tokens
:为用户生成 JWT 令牌,用于请求认证。
引入必要的模块
const express = require ( 'express' ) ;
const cors = require ( 'cors' ) ;
const jwt = require ( 'jsonwebtoken' ) ;
let Gun = require ( 'gun' ) ;
const SEA = require ( 'gun/sea' ) ;
require ( 'bullet-catcher' ) ;
初始化 Express 应用和读取配置
require ( 'dotenv' ) . config ( ) ; const app = express ( ) ;
const port = process. env. PORT || 8765 ;
const APP_KEY_PAIR = JSON . parse ( process. env. APP_KEY_PAIR ) ;
const APP_TOKEN_SECRET = process. env. APP_TOKEN_SECRET ;
Web 服务配置
app. use ( Gun. serve) ;
const server = app. listen ( port, ( ) => { console. log ( ` App listening at http://localhost: ${ port} ` ) ;
} ) ;
function verifyToken ( msg ) { if ( msg?. headers?. accessToken) { try { jwt. verify ( msg. headers. accessToken, APP_TOKEN_SECRET ) ; return true ; } catch ( err) { const error = new Error ( 'Invalid access token' ) ; if ( err. name === 'TokenExpiredError' ) { error. expiredAt = err. expiredAt; } return error; } } return false ;
}
const gun = Gun ( { web: server, isValid: verifyToken,
} ) ;
gun. on ( 'out' , { get: { '#' : { '*' : '' } } } ) ;
gun. user ( ) . auth ( APP_KEY_PAIR , ( { err } ) => { if ( err) { console. error ( err) ; }
} ) ;
API 路由
app. use ( express. json ( ) ) ;
创建授权证书的 API
app. post ( '/api/certificates' , async ( req, res ) => { const { username, pub: userPubKey } = req. body; const policy = [ { '*' : 'profiles' , '+' : '*' } ] ; const expiresAt = Date. now ( ) + 2 * 60 * 60 * 1000 ; try { const certificate = await SEA . certify ( [ userPubKey] , policy, APP_KEY_PAIR , null , { expiry: expiresAt, block: 'blocked' , } ) ; console. log ( ` Successfully created certificate for ${ username} ` ) ; res. status ( 201 ) . send ( { certificate, expires_at: expiresAt } ) ; } catch ( err) { console. error ( ` Error creating certificate for ${ username} : ` , err) ; res. status ( 500 ) . send ( { error: err. message } ) ; }
} ) ;
生成 JWT 令牌的 API
app. post ( '/api/tokens' , async ( req, res ) => { const { username, pub } = req. body; const token = jwt. sign ( { username, pub } , APP_TOKEN_SECRET , { expiresIn: '1h' , } ) ; res. status ( 201 ) . send ( { accessToken: token } ) ;
} ) ;
测试
启动服务器:node ./server.js
使用 curl
或 Postman 测试 /api/certificates
:curl -X POST http://localhost:8765/api/certificates \
-H "Content-Type: application/json" \
-d '{"username": "alice", "pub": "yourUserPubKey"}'
测试 /api/tokens
:curl -X POST http://localhost:8765/api/tokens \
-H "Content-Type: application/json" \
-d '{"username": "alice", "pub": "yourUserPubKey"}'
CG
https://github.com/amark/gun/wiki/SEA.certify#some-examples::Custom personal profiles in a public room