Create Payment and Query Payment requests require encrypting/decrypting and signing the message with the keys (Refer to Request sandbox access and request production secure keys).
The webhook response message does not require any signature.
📘 Prerequisites:
Before you start development work, make sure you have completed the environment setup steps.
The workflow
Please follow the workflow below to sign and verify the signature while sending and processing webhook callbacks.
Workflow of sending request to BIEASES​
Sign the request
The Create Payment and Query Payment request message bodies need to be signed.
Define the request object​
Function Description​
The PaymentDto
class is the core data transfer object for BIEASES API requests and responses, encapsulating all necessary parameters and security information. This class uses the builder pattern to provide convenient object construction methods.
Processing Flow​
- Object Creation: Create specific types of request objects through factory methods
- Parameter Setup: Automatically set necessary security parameters (encryption type, signature type, etc.)
- Timestamp Generation: Automatically generate current timestamp for replay attack prevention
- Data Serialization: Convert business data to JSON string and store in body field
Key Features​
- Security: Support for AES encryption and RSA digital signatures
- Standardization: Unified parameter format and encoding methods
- Flexibility: Support for two main operations - create order and query order
- Replay Protection: Include timestamp field to prevent replay attacks
Use Cases​
- Create payment order requests
- Query payment status requests
- Receive BIEASES response data
import lombok.Data;
/**
* Payment DTO for BIEASES API requests
* This class represents the structure of payment request/response data
*/
@Data
public class PaymentDto {
/** Merchant wallet ID provided by BIEASES */
private String merchantId;
/** API method name (e.g., "bieases.trade.create", "bieases.trade.query") */
private String method;
/** Response format - always "json" for BIEASES API */
private String format = "json";
/** Character encoding - UTF-8 is required */
private String charset = "utf-8";
/** Encryption type - AES is used for body encryption */
private String encryptType = "AES";
/** Signature type - RSA is used for request signing */
private String signType = "RSA";
/** Digital signature of the request parameters */
private String sign;
/** Unix timestamp in milliseconds when the request is made */
private String timestamp;
/** Encrypted request/response body content */
private String body;
/**
* Factory method to build a payment creation request DTO
* @param dto The payment order data transfer object
* @return Configured BieasesPaymentDto for create order API call
*/
public static BieasesPaymentDto buildCreateOrder(PaymentOrderDto dto) {
return BieasesPaymentDto.builder()
.merchantId(dto.getMerchantID()) // Set merchant ID from order data
.method("bieases.trade.create") // API method for creating payment
.format("json") // JSON format response
.charset("utf-8") // UTF-8 encoding
.encryptType("AES") // AES encryption for body
.signType("RSA") // RSA signature for security
.timestamp(String.valueOf(System.currentTimeMillis())) // Current timestamp
.body(JSON.toJSONString(dto)) // Convert order DTO to JSON string
.build();
}
/**
* Factory method to build a payment query request DTO
* @param dto Map containing query parameters (e.g., paymentId)
* @param merchantId The merchant wallet ID
* @return Configured BieasesPaymentDto for query order API call
*/
public static BieasesPaymentDto buildQueryOrder(Map<String, String> dto, String merchantId) {
return BieasesPaymentDto.builder()
.merchantId(merchantId) // Set merchant wallet ID
.method("bieases.trade.query") // API method for querying payment
.format("json") // JSON format response
.charset("utf-8") // UTF-8 encoding
.encryptType("AES") // AES encryption for body
.signType("RSA") // RSA signature for security
.timestamp(String.valueOf(System.currentTimeMillis())) // Current timestamp
.body(JSON.toJSONString(dto)) // Convert query params to JSON
.build();
}
}
Define the response object​
Function Description​
The BieasesResponse
class is a standard response wrapper for BIEASES API, providing a unified response format. This class implements the Serializable
interface to support serialized transmission.
Processing Flow​
- Response Reception: Receive response data from BIEASES server
- Status Parsing: Determine operation success through the code field
- Message Extraction: Get operation results or error information from msg field
- Data Access: Access specific business data through the data field
Field Description​
- code: Response status code (20000 indicates success, other values indicate different types of errors)
- msg: Descriptive message, contains operation confirmation on success, error details on failure
- data: Actual business data of type PaymentDto
Usage Notes​
- Always check the code field to confirm operation success
- The data field may be null in error situations
- The msg field is very important for error troubleshooting
import lombok.Data;
import java.io.Serializable;
/**
* REST API response wrapper for BIEASES payment operations
* This class standardizes the response format from BIEASES API
*
* @author peng.shu
* @since 2024-06-24
*/
@Data
public class BieasesResponse implements Serializable {
/** Response status code (20000 = success, other codes indicate errors) */
private int code;
/** Response message describing the result or error details */
private String msg;
/** Actual response data containing payment information */
private PaymentDto data;
}
Encrypt request body and sign the request​
Function Description​
The EncryptAndSignUtils
class is responsible for request data encryption and digital signing, serving as the core component of BIEASES API security mechanism. This class ensures data confidentiality and integrity during transmission.
Basic Functions​
- AES Encryption: Use symmetric encryption to protect request body data
- RSA Signing: Use asymmetric encryption to generate digital signatures
- Parameter Sorting: Sort parameters alphabetically for signature generation
- Security Validation: Ensure request data has not been tampered with
Processing Flow​
- Data Encryption: Encrypt request body content using AES algorithm
- Parameter Mapping: Convert DTO object to Map for easier processing
- Signature Exclusion: Remove sign field to avoid circular dependency
- Parameter Sorting: Sort all parameters alphabetically by key name
- Content Building: Build parameter string for signature generation
- Digital Signing: Generate RSA signature using merchant private key
- Signature Setting: Set the generated signature back to the original object
Security Principles​
- Confidentiality: AES encryption ensures data content is not stolen
- Integrity: RSA signature ensures data has not been tampered with
- Authentication: Private key signature proves request origin
- Replay Protection: Timestamp participates in signature to prevent replay attacks
Important Notes​
- Private key must be properly secured and never leaked
- Encryption key and IV are provided by BIEASES
- Parameter sorting rules must be consistent with verification side
- Signature field does not participate in signature calculation
Sign your request with your private key.
import cn.hutool.json.JSONUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Utility class for encrypting request body and signing request parameters
* This class handles the security aspects of BIEASES API communication
*/
public class EncryptAndSignUtils {
/** Key name for signature parameter - excluded from signing process */
public static final String SIGN_KEY = "sign";
/**
* Main method to encrypt request body and generate digital signature
* Process: 1) Encrypt body content 2) Sort all parameters 3) Generate signature
*
* @param param payment parameters object containing all request data
* @param encryptKey AES symmetric encryption key provided by BIEASES
* @param iv AES initialization vector for encryption
* @param privateKey merchant's RSA private key for signing
* @return encrypted and signed payment DTO ready for API call
* @throws Exception if encryption or signing process fails
*/
public static BieasesPaymentDto encryptAndSign(BieasesPaymentDto param, String encryptKey, String iv, String privateKey) throws Exception {
// Step 1: Get the original body content before encryption
String bizContent = param.getBody();
// Step 2: Encrypt the body content using AES encryption
String encryptBizContent = BieasesEncrypt.encryptContent(bizContent, param.getEncryptType(), encryptKey, iv);
param.setBody(encryptBizContent);
// Step 3: Convert payment DTO to Map for parameter processing
Map<String, String> paramMap = JSONUtil.toBean(JSONUtil.toJsonStr(param), Map.class);
// Step 4: Remove 'sign' field as it should not be included in signature calculation
paramMap.remove(SIGN_KEY);
// Step 5: Sort parameters alphabetically and create sign content string
String signContent = getSignContent(paramMap);
// Step 6: Generate RSA signature using merchant's private key
String sign = RSAEncryptor.doSign(signContent, privateKey);
// Step 7: Set the generated signature back to the parameter object
param.setSign(sign);
return param;
}
/**
* Creates a sorted parameter string for signature generation
* Format: key1=value1&key2=value2&key3=value3 (alphabetically sorted by key)
*
* @param sortedParams Map of parameters to be signed
* @return URL-encoded parameter string ready for signature generation
*/
public static String getSignContent(Map<String, String> sortedParams) {
StringBuilder content = new StringBuilder();
// Get all parameter keys and sort them alphabetically
List<String> keys = new ArrayList<String>(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
// Build the parameter string in format: key1=value1&key2=value2
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = sortedParams.get(key);
// Only include non-empty key-value pairs
if (StringUtils.areNotEmpty(key, value)) {
content.append(index == 0 ? "" : "&") // Add & separator except for first param
.append(key) // Parameter name
.append("=") // Equals sign
.append(value); // Parameter value
index++;
}
}
return content.toString();
}
}
Verify signature and decrypt response body​
Function Description​
The VerifySignatureUtils
class is responsible for verifying digital signatures from BIEASES responses and decrypting response data, ensuring that received data comes from a trusted source and has not been tampered with.
Basic Functions​
- Signature Verification: Verify response signatures using BIEASES public key
- Data Decryption: Decrypt response body content using AES algorithm
- Security Check: Ensure response data integrity and authenticity
- Exception Handling: Handle verification failures and decryption errors
Processing Flow​
- Parameter Extraction: Convert response DTO to Map for easier processing
- Signature Separation: Remove sign field to prepare verification content
- Content Sorting: Sort parameters alphabetically to build verification string
- Signature Verification: Verify digital signature using BIEASES public key
- Security Check: Throw exception immediately if verification fails
- Data Decryption: Decrypt response body content after verification passes
- Result Return: Return complete decrypted response object
Security Mechanisms​
- Identity Verification: Public key verification ensures response comes from BIEASES
- Integrity Check: Signature verification ensures data has not been tampered with
- Confidentiality Protection: AES decryption retrieves original data content
- Fail Fast: Stop processing immediately if verification fails
Error Handling​
- Signature Verification Failure: Throw
APIException
- Decryption Failure: May be caused by wrong key or corrupted data
- Parameter Exception: Handle null values or format errors
Usage Notes​
- Must use correct BIEASES public key
- AES key and IV must be consistent with encryption
- Never use responses that fail verification
- Ensure parameter sorting rules are consistent with signature generation
Verify the signature and decrypt the response.
import cn.hutool.json.JSONUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Utility class for verifying response signatures and decrypting response data
* This class handles the security verification of BIEASES API responses
*/
public class VerifySignatureUtils {
/** Key name for signature parameter - excluded from signature verification */
private static final String SIGN_KEY = "sign";
/**
* Main method to verify response signature and decrypt response body
* Process: 1) Verify digital signature 2) Decrypt body content if signature is valid
*
* @param param payment response parameters from BIEASES API
* @param encryptKey AES symmetric decryption key provided by BIEASES
* @param iv AES initialization vector for decryption
* @param publicKey BIEASES wallet's RSA public key for signature verification
* @return decrypted payment DTO with verified signature
* @throws BieasesGatewayApiException if signature verification fails
* @throws Exception if decryption process fails
*/
public static BieasesPaymentDto verifySignAndDecrypt(BieasesPaymentDto param, String encryptKey, String iv, String publicKey) {
// Step 1: Convert response DTO to Map for parameter processing
Map<String, String> paramMap = JSONUtil.toBean(JSONUtil.toJsonStr(param), Map.class);
// Step 2: Remove 'sign' field as it should not be included in verification
paramMap.remove(SIGN_KEY);
// Step 3: Sort parameters alphabetically and create verification content string
String signContent = getSignContent(paramMap);
// Step 4: Verify the RSA signature using BIEASES public key
if (!AsymmetricManager.getByName(param.getSignType()).verify(signContent, param.getCharset(), publicKey, param.getSign())) {
throw new APIException("Signature verification failed - Response may be tampered");
}
// Step 5: Get encrypted body content from response
String bizContent = param.getBody();
// Step 6: Decrypt the body content using AES decryption
String decryptedBizContent = BieasesEncrypt.decryptContent(bizContent, param.getEncryptType(), encryptKey, iv);
param.setBody(decryptedBizContent);
return param;
}
/**
* Creates a sorted parameter string for signature verification
* Must match the same format used during signature generation
* Format: key1=value1&key2=value2&key3=value3 (alphabetically sorted by key)
*
* @param sortedParams Map of parameters to be verified
* @return URL-encoded parameter string for signature verification
*/
public static String getSignContent(Map<String, String> sortedParams) {
StringBuilder content = new StringBuilder();
// Get all parameter keys and sort them alphabetically
List<String> keys = new ArrayList<String>(sortedParams.keySet());
Collections.sort(keys);
int index = 0;
// Build the parameter string in the same format as signing process
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = sortedParams.get(key);
// Only include non-empty key-value pairs
if (StringUtils.areNotEmpty(key, value)) {
content.append(index == 0 ? "" : "&") // Add & separator except for first param
.append(key) // Parameter name
.append("=") // Equals sign
.append(value); // Parameter value
index++;
}
}
return content.toString();
}
}
Encrypt and decrypt utility​
Function Description​
The AesEncrypt
class provides AES symmetric encryption and decryption functionality using AES/CBC/PKCS5Padding algorithm to ensure data confidentiality during transmission. This class is a fundamental component for BIEASES API secure communication.
Basic Functions​
- AES Encryption: Convert plaintext data to ciphertext
- AES Decryption: Restore ciphertext data to plaintext
- Base64 Encoding: Handle binary data for text transmission
- Error Handling: Unified exception handling mechanism
Encryption Algorithm Features​
- Algorithm: AES (Advanced Encryption Standard)
- Mode: CBC (Cipher Block Chaining)
- Padding: PKCS5Padding (Standard padding algorithm)
- Encoding: UTF-8 character encoding, Base64 transmission encoding
Processing Flow​
Encryption Flow:​
- Key Decoding: Decode Base64 key and IV to byte arrays
- Parameter Setup: Create AES key specification and IV parameter specification
- Cipher Initialization: Initialize AES cipher in encryption mode
- Data Encryption: Encrypt UTF-8 encoded plaintext to byte array
- Result Encoding: Encode encrypted byte array to Base64 string
Decryption Flow:​
- Key Decoding: Decode Base64 key and IV to byte arrays
- Parameter Setup: Create AES key specification and IV parameter specification
- Cipher Initialization: Initialize AES cipher in decryption mode
- Data Decoding: Decode Base64 ciphertext to byte array
- Data Decryption: Decrypt byte array to get original data
- Result Conversion: Convert decrypted byte array to UTF-8 string
Security Considerations​
- Key Management: Keys are securely generated and distributed by BIEASES
- IV Uniqueness: Use different initialization vectors for each encryption
- Data Integrity: Combined with digital signatures to ensure data integrity
- Transmission Security: Base64 encoding ensures safe transmission of binary data
Exception Handling​
- Encryption Failure: May be caused by wrong key, data format issues, etc.
- Decryption Failure: May be caused by key mismatch, data corruption, etc.
- Encoding Exception: Base64 encoding/decoding errors
- Unified Exception: Use
APIException
to wrap all exceptions
Usage Notes​
- Key and IV must be valid Base64 encoded strings
- Encryption and decryption must use the same key and IV
- Plaintext data uses UTF-8 encoding
- Ciphertext results are transmitted in Base64 format
import com.example.demomall.entity.APIException;
import com.example.demomall.framework.reponse.ResultCode;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* AES encryption/decryption utility class for BIEASES API communication
* Uses AES/CBC/PKCS5Padding algorithm with Base64 encoding
*/
public class AesEncrypt {
/** AES algorithm identifier */
private static final String AES_ALG = "AES";
/** AES cipher transformation: AES algorithm + CBC mode + PKCS5 padding */
private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding";
/**
* Encrypts plaintext using AES encryption
*
* @param plaintext The original text to be encrypted (request body)
* @param keyB64 Base64-encoded AES encryption key provided by BIEASES
* @param ivB64 Base64-encoded initialization vector for CBC mode
* @return Base64-encoded encrypted string
* @throws APIException if encryption process fails
*/
public String encrypt(String plaintext, String keyB64, String ivB64) throws APIException {
// Decode Base64-encoded key and IV to byte arrays
byte[] key = Base64.getDecoder().decode(keyB64);
byte[] iv = Base64.getDecoder().decode(ivB64);
// Create AES key specification and IV parameter specification
SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALG);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher;
byte[] encryptedBytes;
try {
// Initialize AES cipher in encryption mode
cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
// Encrypt the plaintext and get encrypted bytes
encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
// Handle encryption errors with detailed error message
String errorMsg = String.format(ResultCode.ENCRYPT_AES_ERROR.getMsg(),
plaintext, StandardCharsets.UTF_8);
throw new APIException(ResultCode.ENCRYPT_AES_ERROR.getCode(), errorMsg, e);
}
// Return Base64-encoded encrypted string for transmission
return Base64.getEncoder().encodeToString(encryptedBytes);
}
/**
* Decrypts encrypted string using AES decryption
*
* @param encrypted Base64-encoded encrypted string from BIEASES response
* @param keyB64 Base64-encoded AES decryption key provided by BIEASES
* @param ivB64 Base64-encoded initialization vector for CBC mode
* @return Decrypted plaintext string
* @throws APIException if decryption process fails
*/
public String decrypt(String encrypted, String keyB64, String ivB64) throws APIException {
// Decode Base64-encoded key and IV to byte arrays
byte[] key = Base64.getDecoder().decode(keyB64);
byte[] iv = Base64.getDecoder().decode(ivB64);
// Create AES key specification and IV parameter specification
SecretKeySpec keySpec = new SecretKeySpec(key, AES_ALG);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher;
byte[] decryptedBytes;
try {
// Initialize AES cipher in decryption mode
cipher = Cipher.getInstance(AES_CBC_PCK_ALG);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
// Decode Base64 encrypted string to bytes
byte[] decodedBytes = Base64.getDecoder().decode(encrypted);
// Decrypt the bytes to get original content
decryptedBytes = cipher.doFinal(decodedBytes);
} catch (Exception e) {
// Handle decryption errors with detailed error message
String errorMsg = String.format(ResultCode.DECRYPT_AES_ERROR.getMsg(),
encrypted, StandardCharsets.UTF_8);
throw new APIException(ResultCode.DECRYPT_AES_ERROR.getCode(), errorMsg, e);
}
// Return decrypted string in UTF-8 encoding
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
}
Example of signing and verifying signature​
Function Description​
The RSAEncryptor
class provides RSA digital signature and verification functionality, serving as the core component of BIEASES API security authentication system. This class handles RSA key management and digital signature operations, ensuring identity authentication and data integrity between communicating parties.
Basic Functions​
- Digital Signature: Generate request signatures using merchant private key
- Signature Verification: Verify response signatures using BIEASES public key
- Key Management: Handle PKCS8 and X509 format keys
- Base64 Processing: Handle encoding conversion for keys and signatures
Digital Signature Principles​
- Asymmetric Encryption: Use RSA public-private key system
- Signature Algorithm: SHA256withRSA (SHA256 hash + RSA signature)
- Key Formats: PKCS8 (private key) and X509 (public key)
- Encoding Method: Base64 encoding for text transmission
Processing Flow​
Signature Generation Flow (doSign
method):​
- Private Key Loading: Load merchant private key from PKCS8 format string
- Signature Initialization: Initialize signature with SHA256withRSA algorithm
- Private Key Binding: Bind private key to signature for signing
- Data Input: Input content to be signed (UTF-8 encoded) to signature
- Signature Generation: Generate digital signature byte array
- Encoding Output: Encode signature byte array to Base64 string
Signature Verification Flow (doVerify
method):​
- Public Key Loading: Load BIEASES public key from X509 format string
- Verifier Initialization: Initialize verifier with configured algorithm
- Public Key Binding: Bind public key to verifier for verification
- Data Input: Input content to be verified with specified encoding to verifier
- Signature Decoding: Decode Base64 signature to byte array
- Verification Execution: Execute signature verification and return boolean result
Key Loading Flow:​
-
PKCS8 Private Key Loading:
- Validate input parameters (algorithm and input stream)
- Create key factory for corresponding algorithm
- Read key data and decode from Base64
- Generate private key object using PKCS8EncodedKeySpec
-
X509 Public Key Loading:
- Create key factory for corresponding algorithm
- Read key data from input stream
- Decode key data from Base64
- Generate public key object using X509EncodedKeySpec
Security Mechanisms​
- Identity Authentication: Private key signature proves request origin identity
- Data Integrity: Signature verification ensures data has not been tampered with
- Non-repudiation: Digital signatures provide legal-level non-repudiation
- Key Separation: Public-private key separation, private key held only by merchant
Key Format Description​
- PKCS8: Private key standard format, used for merchant signing
- X509: Public key standard format, used for BIEASES verification
- Base64: Text encoding format for binary keys
- PEM: Standard transmission format for keys
Exception Handling​
- Key Parsing Exception: Wrong key format or corruption
- Signature Generation Exception: Unsupported algorithm or invalid key
- Verification Failure: Signature mismatch or wrong key
- Encoding Exception: Base64 encoding/decoding errors
Usage Notes​
- Private Key Security: Merchant private key must be strictly confidential and never leaked
- Public Key Updates: Regularly update BIEASES public key to ensure security
- Algorithm Consistency: Signing and verification must use the same algorithm
- Encoding Uniformity: Ensure character encoding consistency (UTF-8)
- Key Format: Ensure keys conform to PKCS8/X509 standard formats
Performance Considerations​
- Key Caching: Consider caching parsed key objects
- Algorithm Optimization: RSA signature calculation is relatively time-consuming, avoid frequent operations
- Resource Management: Release input streams and other resources promptly
import com.example.demomall.framework.encrypt.code.Base64;
import javax.crypto.Cipher;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA encryption and digital signature utility class for BIEASES API
* Handles RSA key management and signature operations for secure communication
*/
public class RSAEncryptor extends BaseAsymmetricEncryptor {
/**
* Generate RSA digital signature for request parameters
*
* @param content The sorted parameter string to be signed
* @param privateKey Merchant's RSA private key in PKCS8 format
* @return Base64-encoded digital signature
* @throws Exception if signing process fails
*/
public static String doSign(String content, String privateKey) throws Exception {
// Load private key from PKCS8 format string
PrivateKey priKey = getPrivateKeyFromPKCS8(BieasesConstants.SIGN_TYPE_RSA,
new ByteArrayInputStream(privateKey.getBytes()));
// Initialize RSA signature with SHA256 algorithm
Signature signature = Signature.getInstance(BieasesConstants.SIGN_SHA256RSA_ALGORITHMS);
// Initialize signature object with private key for signing
signature.initSign(priKey);
// Feed the content to be signed into signature object
signature.update(content.getBytes(StandardCharsets.UTF_8));
// Generate the digital signature
byte[] signed = signature.sign();
// Return Base64-encoded signature for transmission
return Base64.encodeBase64String(signed);
}
/**
* Verify RSA digital signature from BIEASES response
*
* @param content The sorted parameter string used for verification
* @param charset Character encoding used for content
* @param publicKey BIEASES public key in X509 format
* @param sign Base64-encoded signature to verify
* @return true if signature is valid, false otherwise
* @throws Exception if verification process fails
*/
protected boolean doVerify(String content, String charset, String publicKey, String sign) throws Exception {
// Load public key from X509 format string
PublicKey pubKey = getPublicKeyFromX509("RSA",
new ByteArrayInputStream(publicKey.getBytes()));
// Initialize RSA signature with configured algorithm
Signature signature = Signature.getInstance(getSignAlgorithm());
// Initialize signature object with public key for verification
signature.initVerify(pubKey);
// Feed the content to signature object with proper encoding
if (StringUtils.isEmpty(charset)) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
// Verify the signature and return result
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
/**
* Extract RSA private key from PKCS8 format input stream
*
* @param algorithm RSA algorithm identifier
* @param ins Input stream containing PKCS8 private key data
* @return PrivateKey object for signing operations
* @throws Exception if key parsing fails
*/
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
InputStream ins) throws Exception {
// Validate input parameters
if (ins == null || StringUtils.isEmpty(algorithm)) {
return null;
}
// Create RSA key factory
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
// Read the key data and decode from Base64
byte[] encodedKey = StreamUtil.readText(ins).getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
// Generate private key from PKCS8 specification
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
/**
* Extract RSA public key from X509 format input stream
*
* @param algorithm RSA algorithm identifier
* @param ins Input stream containing X509 public key data
* @return PublicKey object for signature verification
* @throws Exception if key parsing fails
*/
public static PublicKey getPublicKeyFromX509(String algorithm,
InputStream ins) throws Exception {
// Create RSA key factory
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
// Read the key data from input stream
StringWriter writer = new StringWriter();
StreamUtil.io(new InputStreamReader(ins), writer);
// Decode the key data from Base64
byte[] encodedKey = writer.toString().getBytes();
encodedKey = Base64.decodeBase64(encodedKey);
// Generate public key from X509 specification
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
}
}