在Node.js中使用libsodium进行GitHub API秘密加密:UnhandledPromiseRejectionWarning:错误:错误的公钥大小

问题描述

我想通过GitHub REST API设置存储库秘密。我使用docs中的示例:

const sodium = require('tweetsodium');

const key = "base64-encoded-public-key";
const value = "plain-text-secret";

// Convert the message and key to Uint8Array's (Buffer implements that interface)
const messageBytes = Buffer.from(value);
const keyBytes = Buffer.from(key,'base64');

// Encrypt using Libsodium.
const encryptedBytes = sodium.seal(messageBytes,keyBytes);

// Base64 the encrypted secret
const encrypted = Buffer.from(encryptedBytes).toString('base64');

console.log(encrypted);

我收到此错误

(node:6008) UnhandledPromiseRejectionWarning: Error: bad public key size
    at checkBoxLengths (C:\Users\User\probot\node_modules\tweetnacl\nacl-fast.js:2158:54)
    at Function.nacl.Box.before (C:\Users\User\probot\node_modules\tweetnacl\nacl-fast.js:2231:3)
    at Object.nacl.Box (C:\Users\User\probot\node_modules\tweetnacl\nacl-fast.js:2225:20)
    at Object.tweetsodium.seal (C:\Users\User\probot\node_modules\tweetsodium\dist\index.umd.js:53:33)
    at createSecret (C:\Users\User\probot\src\service\secret.js:55:33)
    at Object.<anonymous> (C:\Users\User\probot\src\service\secret.js:73:1)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
(node:6008) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block,or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection,use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:6008) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future,promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

问题:如何正确加密和解​​密机密,以便可以在我的API中使用它?

解决方:@Topaco提到您需要使用base {64}编码的密钥,例如2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU=。这样可以解决上面描述的错误

编辑

我将在不同的存储库中使用不同的秘密。我应该为每个存储库生成一个新的base64编码密钥吗?

解决方法

示例代码不清楚key的实际含义和获取位置。您需要从/repos/{owner}/{repo}/actions/secrets/public-key端点获得的“存储库公共密钥”。

使用存储库公钥以及新机密中的值:

const key = "base64-encoded-public-key"; // this is the repository public key you need to fetch from GitHub
const value = "plain-text-secret"; // the secret value

然后您可以create or update密钥:

  const res = await octokit.actions.createOrUpdateRepoSecret({
    owner: "GITHUBUSER",repo: "GITHUB_REPO",secret_name: "KEY_NAME",encrypted_value: encrypted,});
,

这是我使用的代码。

const crypto = require('crypto');

const sodium = require('tweetsodium');
const { Octokit } = require("@octokit/core");

// Create a personal access token at https://github.com/settings/tokens/new?scopes=repo
const octokit = new Octokit({ auth: process.env.GH_PERSONAL_ACCESS_TOKEN });

module.exports = async () => {
  const encryptionKey = crypto.randomBytes(16).toString('hex');
  const publicKeyResponse = await octokit.request('GET /repos/<USERNAME>/<REPO>/actions/secrets/public-key');
  const publicKey = publicKeyResponse.data.key;
  const publicKeyId = publicKeyResponse.data.key_id;

  // Convert the message and key to Uint8Array's (Buffer implements that interface)
  const messageBytes = Buffer.from(encryptionKey);
  const keyBytes = Buffer.from(publicKey,'base64');

  // Encrypt using LibSodium.
  const encryptedBytes = sodium.seal(messageBytes,keyBytes);

  // Base64 the encrypted secret
  const encryptedEncryptionKey = Buffer.from(encryptedBytes).toString('base64');

  await octokit.request('PUT /repos/<USERNAME>/<REPO>/actions/secrets/ENCRYPTION_KEY',{
    owner: '<USERNAME>',repo: '<REPO>',secret_name: 'ENCRYPTION_KEY',key_id: publicKeyId,encrypted_value: encryptedEncryptionKey,});

  return encryptionKey;
};

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...