前端RSA非对称加密Go解密

Person:

  • JavaScript实现非对称加密

ChatGPT:

  • JavaScript 可以使用公钥密码学算法来实现非对称加密。常用的公钥密码学算法包括 RSA 和 ECC。

下面是一个使用 RSA 算法实现非对称加密的示例:

// 生成 RSA 密钥对
const { publicKey, privateKey } = await window.crypto.subtle.generateKey(
  {
    name: "RSA-OAEP",
    modulusLength: 2048,
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 65537
    hash: "SHA-256",
  },
  true,
  ["encrypt", "decrypt"]
);

// 加密数据
const plaintext = "Hello, world!";
const encryptedData = await window.crypto.subtle.encrypt(
  {
    name: "RSA-OAEP",
  },
  publicKey,
  new TextEncoder().encode(plaintext)
);

// 解密数据
const decryptedData = await window.crypto.subtle.decrypt(
  {
    name: "RSA-OAEP",
  },
  privateKey,
  encryptedData
);
const decryptedText = new TextDecoder().decode(decryptedData);

console.log(decryptedText); // 输出 "Hello, world!"

上面的代码中,首先使用 generateKey 函数生成一个 RSA 密钥对,其中包括公钥和私钥。然后使用 encrypt 函数对数据进行加密,使用 decrypt 函数对加密后的数据进行解密。在加密和解密时都需要指定加密算法,这里使用了 RSA-OAEP 算法。

需要注意的是,在使用非对称加密时,加密和解密所使用的密钥不同,因此需要妥善保管私钥,不要泄露给第三方。

ChatGPT:

  • 如果你要使用 Go 语言对前面示例代码中的加密结果进行解密,可以使用 Go 标准库中的 crypto/rsa 包。

下面是一个示例代码,它可以将前面示例代码中使用 RSA 算法加密的数据解密回原始数据:

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"fmt"
)

func main() {
	// 从字符串中解析 RSA 密钥对
	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		panic(err)
	}
	publicKey := &privateKey.PublicKey

	// 从加密的数据中解密出原始数据
	encryptedData := []byte{ /* 加密后的数据 */ }
	decryptedData, err := rsa.DecryptOAEP(
		sha256.New(),
		rand.Reader,
		privateKey,
		encryptedData,
		nil,
	)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(decryptedData)) // 输出 "Hello, world!"
}

在这个示例中,我们首先使用 rsa.GenerateKey 函数生成一个 RSA 密钥对,然后使用 rsa.DecryptOAEP 函数将加密的数据解密回原始数据。

需要注意的是,在解密时需要使用与加密时相同的填充算法和哈希算法。这里使用了 OAEP 填充和 SHA-256 哈希算法。同时,解密操作的私钥必须与加密操作的公钥相对应。

另外,这个示例中的加密数据 encryptedData 需要从前面的加密代码中获取,然后将其填入到代码中。

Person:

  • 如何把前端加密的数据转换为字符串?

ChatGPT:

  • 将前端加密后的数据转换为字符串,可以使用 ArrayBufferTypedArray 中的一些方法。

首先,将加密后的数据转换为 Uint8Array 类型的数组,可以使用 new Uint8Array(arrayBuffer) 方法。其中,arrayBuffer 是加密后的数据所在的 ArrayBuffer 对象。

然后,可以使用 Array.prototype.join 方法将 Uint8Array 类型的数组转换为字符串。例如,可以使用以下代码将 Uint8Array 类型的数组转换为 Base64 编码后的字符串:

const encryptedData = /* 加密后的数据 */;
const uint8Array = new Uint8Array(encryptedData);
const base64String = btoa(String.fromCharCode.apply(null, uint8Array));

console.log(base64String);

在这个示例中,我们首先将加密后的数据 encryptedData 转换为 Uint8Array 类型的数组 uint8Array。然后,使用 String.fromCharCode.apply(null, uint8Array) 将数组转换为字符串,并使用 btoa 函数将字符串进行 Base64 编码。最后,将编码后的字符串输出到控制台。

需要注意的是,对于大型数据,使用 btoa 可能会导致浏览器崩溃或超时。在这种情况下,可以考虑使用其他的编码方式,例如 base64-js 库,它提供了一个高效的 JavaScript Base64 编解码器。

Person:

  • 实现一个加密的函数,参数是publicKey和输入字符串,函数返回加密后的字符串。

ChatGPT:

  • 要实现一个使用 RSA 算法进行加密的函数,需要使用 JavaScript 中的 crypto 核心模块和 NodeRSA 第三方模块。

下面是一个示例代码,它可以将输入的字符串使用 RSA 算法加密,并返回加密后的字符串:

const crypto = require('crypto');
const NodeRSA = require('node-rsa');

function encrypt(publicKey, inputString) {
  // 将公钥解析为 NodeRSA 对象
  const publicKeyObj = new NodeRSA();
  publicKeyObj.importKey(publicKey, 'pkcs1-public-pem');

  // 使用 RSA 算法对输入字符串进行加密
  const buffer = Buffer.from(inputString, 'utf8');
  const encryptedBuffer = publicKeyObj.encrypt(buffer, 'base64');

  // 返回加密后的字符串
  return encryptedBuffer.toString('utf8');
}

// 示例
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4+bXkJC42FX58+e7CNoNcQyS1
KhAa3+j7VJ/4PGLZb4uRRE1+tmF87z91onm/kA0Fzp+ztuyfHs12pgTUMT0oX9sp
0abQ2e1Wfsd8xtvqwU6Frgn2fqpJWLDHXb27gX9eyAYlLkCfHwAdzIckvfg5c5KR
NL5i5IStZTWYdVu9kwIDAQAB
-----END PUBLIC KEY-----`;
const inputString = 'Hello, world!';
const encryptedString = encrypt(publicKey, inputString);
console.log(encryptedString);

在这个示例中,我们首先使用 NodeRSA 模块将公钥解析为 NodeRSA 对象。然后,使用 NodeRSA 对象的 encrypt 方法对输入字符串进行加密,并将加密后的数据转换为字符串。

需要注意的是,在使用 NodeRSA 对象进行加密时,可以指定加密算法和输出格式。在这个示例中,我们使用了默认的算法 RSAES-PKCS1-v1_5 和输出格式 base64

另外,为了支持 Node.js 中的 Buffer 类型和字符串类型之间的转换,我们在代码中使用了 Buffer.fromBuffer.toString 方法。

Person:

  • 基于浏览器环境的JavaScript实现呢。

ChatGPT:

  • 在浏览器环境下,可以使用 Web Crypto API 来实现基于 RSA 算法的加密。

以下是一个示例代码,它可以将输入的字符串使用 RSA 算法加密,并返回加密后的字符串:

async function encrypt(publicKey, inputString) {
  // 将公钥解析为 CryptoKey 对象
  const publicKeyObj = await window.crypto.subtle.importKey(
    'spki',
    publicKey,
    {
      name: 'RSA-OAEP',
      hash: 'SHA-256',
    },
    true,
    ['encrypt']
  );

  // 使用 RSA 算法对输入字符串进行加密
  const buffer = new TextEncoder().encode(inputString);
  const encryptedBuffer = await window.crypto.subtle.encrypt(
    {
      name: 'RSA-OAEP',
      hash: 'SHA-256',
    },
    publicKeyObj,
    buffer
  );

  // 返回加密后的字符串
  const encryptedArray = new Uint8Array(encryptedBuffer);
  const base64String = btoa(String.fromCharCode.apply(null, encryptedArray));
  return base64String;
}

// 示例
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4+bXkJC42FX58+e7CNoNcQyS1
KhAa3+j7VJ/4PGLZb4uRRE1+tmF87z91onm/kA0Fzp+ztuyfHs12pgTUMT0oX9sp
0abQ2e1Wfsd8xtvqwU6Frgn2fqpJWLDHXb27gX9eyAYlLkCfHwAdzIckvfg5c5KR
NL5i5IStZTWYdVu9kwIDAQAB
-----END PUBLIC KEY-----`;
const inputString = 'Hello, world!';
encrypt(publicKey, inputString).then(console.log);

在这个示例中,我们首先使用 window.crypto.subtle.importKey 方法将公钥解析为 CryptoKey 对象。然后,使用 window.crypto.subtle.encrypt 方法对输入字符串进行加密,并将加密后的数据转换为字符串。

需要注意的是,为了支持将加密后的数据转换为字符串,我们在代码中使用了 Uint8Array 类型和 String.fromCharCode.apply 方法。在这个示例中,我们将加密后的数据转换为 Base64 编码后的字符串。

posted @ 2023-03-25 11:30  让速不让路  阅读(589)  评论(0编辑  收藏  举报