OwlProxy API
  • 简体中文
  • English
  • 简体中文
  • English
  • Product Introduction
  • Product Type
  • Product Billing
  • OpenAPI
    • API Documentation
    • API Guide
    • Change Log
    • LLMs.txt (AI Quick Reference)
    • OpenAPI Specification (AI Exclusive)
    • Error Code
  • Related Agreements
    • /en/system/PrivacyAgreement.html

API Guide

Prerequisites

Obtain your account's Access Key ID and Secret Access Key (AK/SK) for API request authentication. Please contact your technical representative to get them.

Common Request Parameters

Each API request must include the following four parameters in the Headers for authentication, otherwise the API request will not be processed correctly.

Parameter NameTypeExample ValueParameter Description
x-datestring20240301T093700ZTimestamp of the request, using UTC time, accurate to seconds
x-hoststringapi.owlproxy.comAPI access domain
authorizationstringHMAC-SHA256 Credential={AccessKey}, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature={Signature}Signature included in the request
Content-Typestringapplication/jsonMIME type of the resource

Authorization Signature Mechanism

For each HTTPS protocol request, the identity of the requester is verified based on the signature information in the access. This is implemented through encrypted verification using the AccessKey ID and AccessKey Secret (AK/SK) corresponding to the user account.

Manual Signature

Note

Signature requires a series of processing on request parameters, including sorting, concatenation, encryption, etc. This method provides greater flexibility and customization, suitable for developers who have a deep understanding of the signature algorithm. However, manual signature requires developers to write additional code to implement the signature process, which may increase development difficulty and the possibility of errors. Therefore, we still recommend using the SDK to call the API and avoid writing signature code yourself. If you need to understand the principles and specific process of signature calculation, refer to the following documentation.

The manual signature mechanism requires the requester to perform hash value calculation on the request parameters, encrypt them, and send them together with the API request to the server. The server will perform signature calculation on the received request using the same mechanism and compare it with the signature sent by the requester. If the signature verification fails, the request will be rejected.

Obtain your account's Access Key ID and Secret Access Key (AK/SK) for API request authentication. Please contact your technical representative to get them.

Building Canonical Request String (CanonicalRequest)

 String canonicalStringBuilder=
 	"host:"+*${host}*+"\n"+
 	"x-date:"+*${xDate}*+"\n"+
 	"content-type:"+*${contentType}*+"\n"+
 	"signedHeaders:"+*${signedHeaders}*+"\n"+
 	"x-content-sha256:"+*${xContentSha256}*;
FieldDescription
hostRequest service domain. Fixed to: api.owlproxy.com
x-dateRepresents the UTC time of the request, i.e., the value of the X-Date parameter in the request header, using the format following ISO 8601 standard: YYYYMMDD'T'HHMMSS'Z', for example: 20201103T104027Z
content-typeMedia type of the request or response body (application/json)
signedHeadersThe Headers that participate in the signature, one-to-one correspondence with the Headers in CanonicalHeaders. The purpose is to indicate which Headers participate in the signature calculation, thereby ignoring extra Headers added by the proxy to the request. If host and x-date exist in the Header, they must participate. Pseudocode is as follows: SignedHeaders=Lowercase(HeaderName0)+';'+Lowercase(HeaderName1)+";"+...+Lowercase(HeaderNameN) Example: SignedHeaders=content-type;host;x-content-sha256;x-date
x-content-sha256hashSHA256(body) Note: body needs to be space-removed before calculating hashSHA256

Building String to Sign (StringToSign)

The签名字符串 (signature string) mainly contains metadata information about the request and the canonical request, consisting of the signature algorithm, request date, credential scope, and the hash value of the canonical request.

Build the string to sign, pseudocode is as follows:

StringToSign=
	Algorithm+'\n'+
	xDate+'\n'+
	CredentialScope+'\n'+
	hashSHA256(canonicalStringBuilder.getByte())
FieldDescription
AlgorithmRepresents the signature algorithm, currently only HMAC-SHA256 is supported.
x-dateRepresents the UTC time of the request, i.e., the value of the X-Date parameter in the request header, using the format following ISO 8601 standard: YYYYMMDD'T'HHMMSS'Z', for example: 20201103T104027Z
CredentialScopeRepresents the credential scope, format: ${YYYYMMDD}/${service}/request, where ${YYYYMMDD} is the date from X-Date, ${service} is fixed to armcloud-paas, request is a fixed value. See below for "Calculating CredentialScope"
CanonicalRequestRefers to the result of building the canonical request string.
Calculating CredentialScope
String credentialScope = shortXDate+"/"+service+"/request";
	shortXDate: short request time (first 8 characters of x-date, example: 20201103)
	service: service name (fixed to armcloud-paas)
	"/request": fixed value

Signing Key Example

Derived signature key generated by HMAC hash operation sequence

byte[]Signingkey=hmacSHA256(hmacSHA256(hmacSHA256(sk.getBytes(),shortXDate),service),"request");
FieldDescription
skCustomer secret key
shortXDateShort request date
ServiceService name, temporarily fixed to armcloud-paas

Signature Example

signature=HexEncode(hmacSHA256(Signingkey,StringToSign))

Signature Generation Utility Class Example (Java)

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

public class PaasSignUtils {

    public static final String service = "armcloud-paas";

    public static String signature(String contentType, String signedHeaders, String host, String xDate, String sk, byte[] body) throws Exception {

        if (body == null) {
            body = new byte[0];
        }
        String xContentSha256 = hashSHA256(body);
        String shortXDate = xDate.substring(0, 8);

        String canonicalStringBuilder = "host:" + host + "\n" + "x-date:" + xDate + "\n" + "content-type:" + contentType + "\n" + "signedHeaders:" + signedHeaders + "\n" + "x-content-sha256:" + xContentSha256;

        String hashcanonicalString = hashSHA256(canonicalStringBuilder.getBytes());

        String credentialScope = shortXDate + "/" + service + "/request";
        String signString = "HMAC-SHA256" + "\n" + xDate + "\n" + credentialScope + "\n" + hashcanonicalString;

        byte[] signKey = genSigningSecretKeyV4(sk, shortXDate, service);
        return bytesToHex(hmacSHA256(signKey, signString));
    }

    public static String hashSHA256(byte[] content) throws Exception {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            return bytesToHex(md.digest(content));
        } catch (Exception e) {
            throw new Exception("Unable to compute hash while signing request: " + e.getMessage(), e);
        }
    }

    public static byte[] hmacSHA256(byte[] key, String content) throws Exception {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(key, "HmacSHA256"));
            return mac.doFinal(content.getBytes());
        } catch (Exception e) {
            throw new Exception("Unable to calculate a request signature: " + e.getMessage(), e);
        }
    }

    private static byte[] genSigningSecretKeyV4(String secretKey, String date, String service) throws Exception {
        byte[] kDate = hmacSHA256((secretKey).getBytes(), date);
        byte[] kService = hmacSHA256(kDate, service);
        return hmacSHA256(kService, "request");
    }

    public static String bytesToHex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return "";
        }
        final StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }

}

API Call Example (Java)

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@Component
public class ApiRequestUtils {
    private static final String API_HOST = "api.owlproxy.com";
    private static final String CONTENT_TYPE = "application/json;charset=UTF-8";
    private static final String ACCESS_KEY = "Access Key ID";
    private static final String SECRET_ACCESS_KEY = "Secret Access Key";

    public static String sendPostRequest(String url, JSONObject params) {
        String xDate = DateToUTC(LocalDateTime.now());
        HttpPost httpPost = new HttpPost(url);

        httpPost.setHeader("content-type", CONTENT_TYPE);
        httpPost.setHeader("x-host", API_HOST);
        httpPost.setHeader("x-date", xDate);

        String authorizationHeader = getAuthorizationHeader(xDate, params.toJSONString(), SECRET_ACCESS_KEY);
        httpPost.setHeader("authorization", authorizationHeader);

        StringEntity entity = new StringEntity(params.toJSONString(), StandardCharsets.UTF_8);
        httpPost.setEntity(entity);

        try (CloseableHttpClient httpClient = HttpClients.createDefault();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {

            HttpEntity responseEntity = response.getEntity();
            return EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);

        } catch (Exception e) {
            throw new RuntimeException("Request failed", e);
        }
    }

    public static String DateToUTC(LocalDateTime dateTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd'T'HHmmss'Z'");
        return dateTime.format(formatter);
    }

    private static String getSign(String xDate, String sk, String requestBody) throws Exception {
        String body = requestBody == null ? null : JSONObject.parseObject(requestBody, Feature.OrderedField).toJSONString();
        return PaasSignUtils.signature(CONTENT_TYPE, "content-type;host;x-content-sha256;x-date", API_HOST, xDate, sk, body == null ? null : body.getBytes(StandardCharsets.UTF_8));
    }

    private static String getAuthorizationHeader(String currentTimestamp, String body, String sk) {
        try {
            String sign = getSign(currentTimestamp, sk, body);
            return String.format("HMAC-SHA256 Credential=%s, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature=%s", ACCESS_KEY, sign);
        } catch (Exception e) {
            throw new RuntimeException("Failed to generate signature", e);
        }
    }
}

API Call Example (Python)

import binascii
import datetime
import hmac
import hashlib
import json
import requests


def get_signature(data, x_date, host, content_type, signed_headers, sk):
    json_string = json.dumps(data, separators=(',', ':'), ensure_ascii = False)

    hash_object = hashlib.sha256(json_string.encode())
    x_content_sha256 = hash_object.hexdigest()

    canonical_string_builder = (
        f"host:{host}\n"
        f"x-date:{x_date}\n"
        f"content-type:{content_type}\n"
        f"signedHeaders:{signed_headers}\n"
        f"x-content-sha256:{x_content_sha256}"
    )

    short_x_date = x_date[:8]
    service = "armcloud-paas"

    credential_scope = "{}/{}/request".format(short_x_date, service)

    algorithm = "HMAC-SHA256"

    hash_sha256 = hashlib.sha256(canonical_string_builder.encode()).hexdigest()
    string_to_sign = (
            algorithm + '\n' +
            x_date + '\n' +
            credential_scope + '\n' +
            hash_sha256
    )

    first_hmac = hmac.new(sk.encode(), digestmod=hashlib.sha256)
    first_hmac.update(short_x_date.encode())
    first_hmac_result = first_hmac.digest()

    second_hmac = hmac.new(first_hmac_result, digestmod=hashlib.sha256)
    second_hmac.update(service.encode())
    second_hmac_result = second_hmac.digest()

    signing_key = hmac.new(second_hmac_result, b'request', digestmod=hashlib.sha256).digest()

    signature_bytes = hmac.new(signing_key, string_to_sign.encode(), hashlib.sha256).digest()

    signature = binascii.hexlify(signature_bytes).decode()

    return signature


def owl_url_util(url, data, AccessKey, sk):
    x_date = datetime.datetime.now().strftime("%Y%m%dT%H%M%SZ")
    content_type = "application/json;charset=UTF-8"
    signed_headers = f"content-type;host;x-content-sha256;x-date"
    ShortDate = x_date[:8]
    host = "api.owlproxy.com"

    signature = get_signature(data, x_date, host, content_type, signed_headers, sk)
    url = f"https://api.owlproxy.com{url}"

    payload = json.dumps(data, ensure_ascii = False)
    headers = {
        'content-type': "application/json;charset=UTF-8",
        'x-date': x_date,
        'x-host': "api.owlproxy.com",
        'authorization': f"HMAC-SHA256 Credential={AccessKey}, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature={signature}"
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    return response.json()

API Call Example (Node.js)

const CryptoJS = require("crypto-js");
const moment = require("moment");
const axios = require("axios");

class OwlAPISigner {
  constructor(accessKeyId, secretAccessKey) {
    this.accessKeyId = accessKeyId;
    this.secretAccessKey = secretAccessKey;
    this.contentType = "application/json;charset=UTF-8";
    this.host = "api.owlproxy.com";
    this.service = "armcloud-paas";
    this.algorithm = "HMAC-SHA256";
  }

  signRequest(requestOptions) {
    const { method, path, queryParams = {}, body = null } = requestOptions;

    let params = "";
    if (method === "POST" && body) {
      params = typeof body === "string" ? body : JSON.stringify(body);
    } else if (method === "GET" && Object.keys(queryParams).length > 0) {
      params = new URLSearchParams(queryParams).toString();
    }

    const xDate = moment().utc().format("YYYYMMDDTHHmmss[Z]");
    const shortXDate = xDate.substring(0, 8);
    const credentialScope = `${shortXDate}/${this.service}/request`;

    const canonicalString = [
      `host:${this.host}`,
      `x-date:${xDate}`,
      `content-type:${this.contentType}`,
      `signedHeaders:content-type;host;x-content-sha256;x-date`,
      `x-content-sha256:${CryptoJS.SHA256(params).toString()}`,
    ].join("\n");

    const stringToSign = [
      this.algorithm,
      xDate,
      credentialScope,
      CryptoJS.SHA256(canonicalString).toString(),
    ].join("\n");

    const kDate = CryptoJS.HmacSHA256(shortXDate, this.secretAccessKey);
    const kService = CryptoJS.HmacSHA256(this.service, kDate);
    const signKey = CryptoJS.HmacSHA256("request", kService);

    const sign = CryptoJS.HmacSHA256(stringToSign, signKey);
    const signature = sign.toString(CryptoJS.enc.Hex);

    const authorization = [
      `HMAC-SHA256 Credential=${this.accessKeyId}/${credentialScope}`,
      `SignedHeaders=content-type;host;x-content-sha256;x-date`,
      `Signature=${signature}`,
    ].join(", ");

    return {
      "x-date": xDate,
      "x-host": this.host,
      authorization: authorization,
      "content-type": this.contentType,
    };
  }
}

API Call Example (Go)

package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"sort"
	"strings"
	"time"
)

type OwlAPISigner struct {
	AccessKeyId     string
	SecretAccessKey string
	ContentType     string
	Host            string
	Service         string
	Algorithm       string
}

func NewOwlAPISigner(accessKeyId, secretAccessKey string) *OwlAPISigner {
	return &OwlAPISigner{
		AccessKeyId:     accessKeyId,
		SecretAccessKey: secretAccessKey,
		ContentType:     "application/json;charset=UTF-8",
		Host:            "api.owlproxy.com",
		Service:         "armcloud-paas",
		Algorithm:       "HMAC-SHA256",
	}
}

func sha256Hex(data string) string {
	hash := sha256.Sum256([]byte(data))
	return hex.EncodeToString(hash[:])
}

func hmacSHA256(key []byte, data string) []byte {
	h := hmac.New(sha256.New, key)
	h.Write([]byte(data))
	return h.Sum(nil)
}

func (s *OwlAPISigner) SignRequest(method, path string,
	queryParams map[string]string,
	body interface{}) map[string]string {
	var paramStr string
	if method == http.MethodPost && body != nil {
		bodyBytes, _ := json.Marshal(body)
		paramStr = string(bodyBytes)
	} else if method == http.MethodGet && len(queryParams) > 0 {
		var queryParts []string
		for k, v := range queryParams {
			queryParts = append(queryParts, url.QueryEscape(k)+"="+url.QueryEscape(v))
		}
		sort.Strings(queryParts)
		paramStr = strings.Join(queryParts, "&")
	}

	xDate := time.Now().UTC().Format("20060102T150405Z")
	shortDate := xDate[:8]
	credentialScope := fmt.Sprintf("%s/%s/request", shortDate, s.Service)

	canonicalString := fmt.Sprintf(
		"host:%s\nx-date:%s\ncontent-type:%s\nsignedHeaders:content-type;host;x-content-sha256;x-date\nx-content-sha256:%s",
		s.Host,
		xDate,
		s.ContentType,
		sha256Hex(paramStr),
	)

	stringToSign := fmt.Sprintf(
		"%s\n%s\n%s\n%s",
		s.Algorithm,
		xDate,
		credentialScope,
		sha256Hex(canonicalString),
	)

	kDate := hmacSHA256([]byte(s.SecretAccessKey), shortDate)
	kService := hmacSHA256(kDate, s.Service)
	signKey := hmacSHA256(kService, "request")

	signature := hex.EncodeToString(hmacSHA256(signKey, stringToSign))

	authorization := fmt.Sprintf(
		"HMAC-SHA256 Credential=%s/%s, SignedHeaders=content-type;host;x-content-sha256;x-date, Signature=%s",
		s.AccessKeyId,
		credentialScope,
		signature,
	)

	return map[string]string{
		"x-date":        xDate,
		"x-host":        s.Host,
		"authorization": authorization,
		"content-type":  s.ContentType,
	}
}

API Call Example (PHP)

<?php

class OwlAPISigner
{
  private $accessKeyId;
  private $secretAccessKey;
  private $contentType = "application/json;charset=UTF-8";
  private $host = "api.owlproxy.com";
  private $service = "armcloud-paas";
  private $algorithm = "HMAC-SHA256";

  public function __construct($accessKeyId, $secretAccessKey)
  {
    $this->accessKeyId = $accessKeyId;
    $this->secretAccessKey = $secretAccessKey;
  }

  public function signRequest($method, $path, $queryParams = [], $body = null)
  {
    $params = "";
    if (strtoupper($method) === "POST" && $body !== null) {
      $params = is_string($body) ? $body : json_encode($body, JSON_UNESCAPED_UNICODE);
    } elseif (strtoupper($method) === "GET" && !empty($queryParams)) {
      $params = http_build_query($queryParams);
    }

    $xDate = gmdate("Ymd\THis\Z");
    $shortXDate = substr($xDate, 0, 8);
    $credentialScope = "$shortXDate/{$this->service}/request";

    $xContentSha256 = hash("sha256", $params);

    $canonicalString = implode("\n", [
      "host:{$this->host}",
      "x-date:$xDate",
      "content-type:{$this->contentType}",
      "signedHeaders:content-type;host;x-content-sha256;x-date",
      "x-content-sha256:$xContentSha256"
    ]);

    $hashedCanonicalString = hash("sha256", $canonicalString);

    $stringToSign = implode("\n", [
      $this->algorithm,
      $xDate,
      $credentialScope,
      $hashedCanonicalString
    ]);

    $kDate = hash_hmac("sha256", $shortXDate, $this->secretAccessKey, true);
    $kService = hash_hmac("sha256", $this->service, $kDate, true);
    $signKey = hash_hmac("sha256", "request", $kService, true);

    $signature = hash_hmac("sha256", $stringToSign, $signKey);

    $authorization = implode(", ", [
      "{$this->algorithm} Credential={$this->accessKeyId}/$credentialScope",
      "SignedHeaders=content-type;host;x-content-sha256;x-date",
      "Signature=$signature"
    ]);

    return [
      "x-date: $xDate",
      "x-host: {$this->host}",
      "authorization: $authorization",
      "content-type: {$this->contentType}"
    ];
  }
}

API Call Example (C#/.NET)

using System;
using System.Net.Http;
using System.Text;
using System.Security.Cryptography;
using System.Text.Json;
using System.Collections.Generic;

public class OwlAPISigner
{
    private readonly string accessKeyId;
    private readonly string secretAccessKey;
    private readonly string contentType = "application/json;charset=utf-8";
    private readonly string host = "api.owlproxy.com";
    private readonly string service = "armcloud-paas";
    private readonly string algorithm = "HMAC-SHA256";

    public OwlAPISigner(string accessKeyId, string secretAccessKey)
    {
        this.accessKeyId = accessKeyId;
        this.secretAccessKey = secretAccessKey;
    }

    public Dictionary<string, string> SignRequest(string method, string path, Dictionary<string, string>? queryParams = null, object? body = null)
    {
        string paramsString = "";

        if (method == "POST" && body != null)
        {
            paramsString = JsonSerializer.Serialize(body);
        }
        else if (method == "GET" && queryParams != null)
        {
            var query = new FormUrlEncodedContent(queryParams).ReadAsStringAsync().Result;
            paramsString = query;
        }

        var utcNow = DateTime.UtcNow;
        var xDate = utcNow.ToString("yyyyMMdd'T'HHmmss'Z'");
        var shortXDate = utcNow.ToString("yyyyMMdd");
        var credentialScope = $"{shortXDate}/{service}/request";

        var payloadHash = SHA256Hex(paramsString);

        var canonicalString = string.Join("\n", new[]
                                      {
                                          $"host:{host}",
                                          $"x-date:{xDate}",
                                          $"content-type:{contentType}",
                                          $"signedHeaders:content-type;host;x-content-sha256;x-date",
                                          $"x-content-sha256:{payloadHash}"
                                          });

        var stringToSign = string.Join("\n", new[]
                                   {
                                       algorithm,
                                       xDate,
                                       credentialScope,
                                       SHA256Hex(canonicalString)
                                       });


        var kDate = HmacSHA256(shortXDate, secretAccessKey);
        var kService = HmacSHA256(service, kDate);
        var signKey = HmacSHA256("request", kService);

        var signature = ByteArrayToHex(HmacSHA256(stringToSign, signKey));

        var authorization = string.Join(", ", new[]
                                    {
                                        $"{algorithm} Credential={accessKeyId}/{credentialScope}",
                                        "SignedHeaders=content-type;host;x-content-sha256;x-date",
                                        $"Signature={signature}"
                                        });

        return new Dictionary<string, string>
        {
            { "x-date", xDate },
            { "x-host", host },
            { "authorization", authorization },
            { "content-type", contentType }
        };
    }

    private static string SHA256Hex(string data)
    {
        using var sha256 = SHA256.Create();
        byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(data));
        return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
    }

    private static byte[] HmacSHA256(string data, string key)
    {
        return HmacSHA256(data, Encoding.UTF8.GetBytes(key));
    }

    private static byte[] HmacSHA256(string data, byte[] key)
    {
        using var hmac = new HMACSHA256(key);
        return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
    }

    private static string ByteArrayToHex(byte[] bytes)
    {
        return BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant();
    }
}

Data Encryption/Decryption Example

Java AES GCM Decryption

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class AESUtils {
    private static final String AES = "AES";
    private static final String AES_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
    private static final int GCM_TAG_LENGTH = 16;
    private static final int GCM_IV_LENGTH = 12;

    private static SecretKeySpec getKeyFromPassword(String password) throws NoSuchAlgorithmException {
        MessageDigest sha = MessageDigest.getInstance("SHA-256");
        byte[] key = sha.digest(password.getBytes());
        return new SecretKeySpec(key, AES);
    }

    public static byte[] generateIv() {
        byte[] iv = new byte[GCM_IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        return iv;
    }

    public static String encrypt(String input, String key) {
        try {
            SecretKeySpec secretKeySpec = getKeyFromPassword(key);
            byte[] iv = generateIv();
            Cipher cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec);
            byte[] cipherText = cipher.doFinal(input.getBytes());

            String ivString = Base64.getEncoder().encodeToString(iv);
            String cipherTextString = Base64.getEncoder().encodeToString(cipherText);
            return ivString + ":" + cipherTextString;
        } catch (Exception e) {
            return null;
        }
    }

    public static String decrypt(String encryptedData, String key) {
        try {
            SecretKeySpec secretKeySpec = getKeyFromPassword(key);

            String[] parts = encryptedData.split(":");
            String ivString = parts[0];
            String cipherTextString = parts[1];

            byte[] iv = Base64.getDecoder().decode(ivString);
            byte[] cipherText = Base64.getDecoder().decode(cipherTextString);

            Cipher cipher = Cipher.getInstance(AES_CIPHER_ALGORITHM);
            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
            byte[] plainText = cipher.doFinal(cipherText);
            return new String(plainText);
        } catch (Exception e) {
            return null;
        }
    }
}
Prev
API Documentation
Next
Change Log