genkey
 
generateAppKey.js
 
const SEA = require('gun/sea');
// 生成密钥对
SEA.pair().then((pair) => {
  // 输出提示信息
  console.log('This is your secret app key pair.\nAdd 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