logo
Development
Search
AiToken Encryption and Issuance

AiToken Encryption and Issuance

Overview

AiToken is the core credential for workspace integration — it encapsulates the organization ID and employee account email, encrypts them with an RSA public key, and concatenates them into a dedicated login URL, allowing enterprise employees to open the workspace in a mobile APP without logging in.


Obtaining the Public Key

  1. Open the Web console → Space ManagementAdvanced SettingsBrandIntegration
  2. In the Integration area, locate the Public Key and click to view or copy it
  3. If you need to refresh the key (uncommon, and it will invalidate all previously issued Tokens), click Reset

Encrypting an AiToken as an Enterprise Employee

Process Overview

Step 1: Member email ─── RSA encryption (public key) ───► emailEncrypted bytes Step 2: emailEncrypted ─── Base64 encoding ───► emailRSAStr Step 3: {projectId}:{emailRSAStr} string concatenation Step 4: Concatenated string ─── Base64 encoding ───► final AiToken
                      
                      Step 1: Member email ─── RSA encryption (public key) ───► emailEncrypted bytes
Step 2: emailEncrypted ─── Base64 encoding ───► emailRSAStr
Step 3: {projectId}:{emailRSAStr} string concatenation
Step 4: Concatenated string ─── Base64 encoding ───► final AiToken

                    
This code block in the floating window

Algorithm Parameters

Parameter Value
RSA algorithm RSA/ECB/PKCS1Padding (i.e. RSAES-PKCS1-V1_5)
Public key format X.509 (SubjectPublicKeyInfo), Base64 encoded
Output encoding Base64 twice

Java Encryption Code Example

import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import javax.crypto.Cipher; public class Main { private static final String RSA_ALGORITHM = "RSA"; private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding"; /** * Encrypts data using RSA public key. * * @param data The data to encrypt. * @param publicKeyStr The Base64 encoded RSA public key. * @return Encrypted data bytes. */ public static byte[] encrypt(byte[] data, String publicKeyStr) throws Exception { byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM); PublicKey publicKey = keyFactory.generatePublic(keySpec); Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } /** * Generates a login key by encrypting the email and combining with projectId. * * @param projectId The project ID. * @param email The user's email. * @param publicKey The Base64 encoded RSA public key. * @return The final login key string. * @throws Exception if encryption fails. */ public static String generateLoginKey(String projectId, String email, String publicKey) throws Exception { byte[] emailEncrypted = encrypt(email.getBytes(StandardCharsets.UTF_8), publicKey); String emailRSAStr = Base64.getEncoder().encodeToString(emailEncrypted); String keyStr = projectId + ":" + emailRSAStr; return Base64.getEncoder().encodeToString(keyStr.getBytes(StandardCharsets.UTF_8)); } public static void main(String[] args) { String projectId = "your project ID"; String email = "your email"; String publicKey = "your public key"; try { String key = generateLoginKey(projectId, email, publicKey); System.out.println(key); } catch (Exception e) { System.err.println("Failed to generate login key: " + e.getMessage()); } } }
                      
                      import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class Main {

    private static final String RSA_ALGORITHM = "RSA";
    private static final String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";

    /**
     * Encrypts data using RSA public key.
     *
     * @param data         The data to encrypt.
     * @param publicKeyStr The Base64 encoded RSA public key.
     * @return Encrypted data bytes.
     */
    public static byte[] encrypt(byte[] data, String publicKeyStr) throws Exception {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(keySpec);

        Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(data);
    }

    /**
     * Generates a login key by encrypting the email and combining with projectId.
     *
     * @param projectId The project ID.
     * @param email     The user's email.
     * @param publicKey The Base64 encoded RSA public key.
     * @return The final login key string.
     * @throws Exception if encryption fails.
     */
    public static String generateLoginKey(String projectId, String email, String publicKey) throws Exception {
        byte[] emailEncrypted = encrypt(email.getBytes(StandardCharsets.UTF_8), publicKey);
        String emailRSAStr = Base64.getEncoder().encodeToString(emailEncrypted);
        String keyStr = projectId + ":" + emailRSAStr;
        return Base64.getEncoder().encodeToString(keyStr.getBytes(StandardCharsets.UTF_8));
    }

    public static void main(String[] args) {
        String projectId = "your project ID";
        String email = "your email";
        String publicKey = "your public key";

        try {
            String key = generateLoginKey(projectId, email, publicKey);
            System.out.println(key);
        } catch (Exception e) {
            System.err.println("Failed to generate login key: " + e.getMessage());
        }
    }
}

                    
This code block in the floating window

TypeScript Encryption Code Example

import * as forge from 'node-forge'; /** * Encrypt data using RSA public key * @param data Data to be encrypted * @param publicKeyStr Base64 encoded public key string * @returns Encrypted byte array */ export function encrypt(data: string, publicKeyStr: string): Uint8Array { try { // Decode Base64 public key const publicKeyBytes = forge.util.decode64(publicKeyStr); // Create public key object const publicKey = forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyBytes)); // Use RSA encryption with PKCS1 padding (consistent with Java's default behavior) const encrypted = publicKey.encrypt(data, 'RSAES-PKCS1-V1_5'); // Convert forge's byte string to Uint8Array const bytes = new Uint8Array(encrypted.length); for (let i = 0; i < encrypted.length; i++) { bytes[i] = encrypted.charCodeAt(i) & 0xff; } return bytes; } catch (error) { throw new Error(`RSA encryption failed: ${error}`); } } /** * Convert byte array to Base64 string * @param bytes Byte array * @returns Base64 encoded string */ export function bytesToBase64(bytes: Uint8Array): string { // Convert Uint8Array to string, then use forge's encode64 const binaryString = Array.from(bytes, byte => String.fromCharCode(byte)).join(''); return forge.util.encode64(binaryString); } /** * Convert string to Base64 * @param str String to be encoded * @returns Base64 encoded string */ export function stringToBase64(str: string): string { return forge.util.encode64(str); } /** * Main function - Generate encrypted key string * @param projectId Project ID * @param email Email address * @param publicKey Base64 encoded RSA public key * @returns Final encrypted Base64 string */ export function generateEncryptedKey(projectId: string, email: string, publicKey: string): string { // Use RSA to encrypt email const emailRSAEncrypt = encrypt(email, publicKey); // Convert encryption result to Base64 const emailRSAStr = bytesToBase64(emailRSAEncrypt); // Combine projectId and encrypted email const keyStr = `${projectId}:${emailRSAStr}`; // Encode the entire string with Base64 const result = stringToBase64(keyStr); return result; } // Generate AiToken example // generateEncryptedKey(projectId, email, publicKey)
                      
                      import * as forge from 'node-forge';

/**
 * Encrypt data using RSA public key
 * @param data Data to be encrypted
 * @param publicKeyStr Base64 encoded public key string
 * @returns Encrypted byte array
 */
export function encrypt(data: string, publicKeyStr: string): Uint8Array {
  try {
    // Decode Base64 public key
    const publicKeyBytes = forge.util.decode64(publicKeyStr);

    // Create public key object
    const publicKey = forge.pki.publicKeyFromAsn1(forge.asn1.fromDer(publicKeyBytes));

    // Use RSA encryption with PKCS1 padding (consistent with Java's default behavior)
    const encrypted = publicKey.encrypt(data, 'RSAES-PKCS1-V1_5');

    // Convert forge's byte string to Uint8Array
    const bytes = new Uint8Array(encrypted.length);
    for (let i = 0; i < encrypted.length; i++) {
      bytes[i] = encrypted.charCodeAt(i) & 0xff;
    }
    return bytes;
  } catch (error) {
    throw new Error(`RSA encryption failed: ${error}`);
  }
}

/**
 * Convert byte array to Base64 string
 * @param bytes Byte array
 * @returns Base64 encoded string
 */
export function bytesToBase64(bytes: Uint8Array): string {
  // Convert Uint8Array to string, then use forge's encode64
  const binaryString = Array.from(bytes, byte => String.fromCharCode(byte)).join('');
  return forge.util.encode64(binaryString);
}

/**
 * Convert string to Base64
 * @param str String to be encoded
 * @returns Base64 encoded string
 */
export function stringToBase64(str: string): string {
  return forge.util.encode64(str);
}

/**
 * Main function - Generate encrypted key string
 * @param projectId Project ID
 * @param email Email address
 * @param publicKey Base64 encoded RSA public key
 * @returns Final encrypted Base64 string
 */
export function generateEncryptedKey(projectId: string, email: string, publicKey: string): string {
  // Use RSA to encrypt email
  const emailRSAEncrypt = encrypt(email, publicKey);

  // Convert encryption result to Base64
  const emailRSAStr = bytesToBase64(emailRSAEncrypt);

  // Combine projectId and encrypted email
  const keyStr = `${projectId}:${emailRSAStr}`;

  // Encode the entire string with Base64
  const result = stringToBase64(keyStr);

  return result;
}

// Generate AiToken example
// generateEncryptedKey(projectId, email, publicKey)

                    
This code block in the floating window

Generating the Dedicated Login URL

Generate the employee account's dedicated login URL in the format {Workspace Integration URL}?{AiToken}:

https://gptbots.ai/space/h5/home?AiToken={encrypted AiToken}&hideClose=true
                      
                      https://gptbots.ai/space/h5/home?AiToken={encrypted AiToken}&hideClose=true

                    
This code block in the floating window

When an enterprise employee opens the dedicated encrypted login URL for their dedicated employee account email in the mobile APP, they can open the corresponding workspace without logging in.


Security Considerations

Consideration Description
Public key security The public key can be distributed publicly, but the issuance process should be completed on the server side to avoid the client directly holding the project ID
Token validity AiToken has no concept of an expiration period; it is recommended to issue it via the backend and avoid long-term caching on the APP side
Email matching The email in the AiToken must be that of a member that already exists in the workspace, otherwise the user will be prompted as nonexistent
Organization binding The same project ID (projectId) corresponds to one organization, and the member must belong to that organization
HTTPS The integration URL must be accessed over HTTPS to prevent the Token from being leaked in transit