跳转至

RSA PKCS#1 加密

调用代理商登录相关接口时,密码不能明文传输。请使用平台提供的 RSA 公钥,按 PKCS#1 填充加密,再把密文编成 URL-Safe Base64 后写入请求体。

适用场景

加密约定

项目 取值
算法 RSA
填充 PKCS#1 v1.5(Java 中对应 RSA/ECB/PKCS1Padding
明文编码 UTF-8
密文编码 URL-Safe Base64,可去掉 = 填充

平台解密时兼容标准 Base64 与 URL-Safe Base64。建议按 URL-Safe 输出,避免 +/ 在 JSON 或 URL 中被转义。

注意:调用平台接口时,必须使用平台提供的公钥。个人中心配置的公钥只用于平台回推密码,两把密钥不能混用。完整接入步骤见 自有平台接入一键登录

平台 RSA 公钥

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC9kMNVuFE+2qnb1vXjlRmjKhd
HR0AEe3i/p0iQNwB082raTulbM2NNdlstG+otWweScbfxwdIj2zylVm31kdEt5yp
wOD4rzDq8MEK51R9wXLzPxPAbJK48occlTdfuh6hX2nK11Toe4D0GaMsE++SanE5
6/d49uXc/ZOrQeAk3QIDAQAB
-----END PUBLIC KEY-----

加密示例

以下示例将明文 ExamplePwd1 加密为请求体中的密文。请将公钥与明文替换为实际值。

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

public class RsaPkcs1EncryptTest {

    public static void main(String[] args) throws Exception {
        String publicKeyPem = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC9kMNVuFE+2qnb1vXjlRmjKhd"
                + "HR0AEe3i/p0iQNwB082raTulbM2NNdlstG+otWweScbfxwdIj2zylVm31kdEt5yp"
                + "wOD4rzDq8MEK51R9wXLzPxPAbJK48occlTdfuh6hX2nK11Toe4D0GaMsE++SanE5"
                + "6/d49uXc/ZOrQeAk3QIDAQAB";
        String plainText = "ExamplePwd1";

        byte[] keyBytes = Base64.decodeBase64(publicKeyPem);
        RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(keyBytes));

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        String cipherText = Base64.encodeBase64URLSafeString(cipher.doFinal(plainText.getBytes("UTF-8")));
        System.out.println(cipherText);
    }
}
package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "fmt"
    "strings"
)

func main() {
    publicKeyPem := `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC9kMNVuFE+2qnb1vXjlRmjKhd
HR0AEe3i/p0iQNwB082raTulbM2NNdlstG+otWweScbfxwdIj2zylVm31kdEt5yp
wOD4rzDq8MEK51R9wXLzPxPAbJK48occlTdfuh6hX2nK11Toe4D0GaMsE++SanE5
6/d49uXc/ZOrQeAk3QIDAQAB
-----END PUBLIC KEY-----`
    plainText := "ExamplePwd1"

    block, _ := pem.Decode([]byte(publicKeyPem))
    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    cipherBytes, err := rsa.EncryptPKCS1v15(rand.Reader, pub.(*rsa.PublicKey), []byte(plainText))
    if err != nil {
        panic(err)
    }
    cipherText := strings.TrimRight(base64.URLEncoding.EncodeToString(cipherBytes), "=")
    fmt.Println(cipherText)
}
const crypto = require('crypto');

const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC9kMNVuFE+2qnb1vXjlRmjKhd
HR0AEe3i/p0iQNwB082raTulbM2NNdlstG+otWweScbfxwdIj2zylVm31kdEt5yp
wOD4rzDq8MEK51R9wXLzPxPAbJK48occlTdfuh6hX2nK11Toe4D0GaMsE++SanE5
6/d49uXc/ZOrQeAk3QIDAQAB
-----END PUBLIC KEY-----`;
const plainText = 'ExamplePwd1';

const cipherBytes = crypto.publicEncrypt(
  {
    key: publicKeyPem,
    padding: crypto.constants.RSA_PKCS1_PADDING
  },
  Buffer.from(plainText, 'utf8')
);
console.log(cipherBytes.toString('base64url'));

解密回推密码

平台回推 newPassword 时,使用您在个人中心配置的公钥加密。请用配对私钥按 PKCS#1 解密。

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

public class RsaPkcs1DecryptTest {

    public static void main(String[] args) throws Exception {
        String privateKeyPem = "{您的PKCS8私钥Base64}";
        String cipherText = "{RSA密文}";

        byte[] keyBytes = Base64.decodeBase64(privateKeyPem);
        RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
                .generatePrivate(new PKCS8EncodedKeySpec(keyBytes));

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        String plainText = new String(cipher.doFinal(Base64.decodeBase64(cipherText)), "UTF-8");
        System.out.println(plainText);
    }
}

验证结果

  • 将加密结果填入接口请求体后,不再出现 解析失败,请确认RSA公钥是否正确
  • 使用同一把私钥解密密文,应得到原始明文密码。

常见问题

提示解析失败,请确认 RSA 公钥是否正确

请确认使用的是本文中的平台公钥,填充为 PKCS#1 v1.5,而不是 OAEP。不要使用个人中心配置的那把公钥加密后调用平台接口。

密文里出现加号或斜杠导致请求失败

请输出 URL-Safe Base64(+ 改为 -/ 改为 _),或对请求体做正确的 JSON 转义。

个人中心测试加密成功,但接口解密失败

个人中心的「测试 RSA 公钥」只验证您自己的公钥。调用平台接口仍须用平台公钥加密。

相关文档