การเข้ารหัสและออก AiToken

การเข้ารหัสและออก AiToken

ภาพรวม

AiToken คือข้อมูลรับรองหลักสำหรับการผสานรวมพื้นที่ทำงาน โดยมันห่อหุ้ม รหัสองค์กร (organization ID) และ อีเมลบัญชีพนักงาน เอาไว้ เมื่อเข้ารหัสด้วยกุญแจสาธารณะ RSA แล้วนำมาต่อกันเป็น URL สำหรับเข้าสู่ระบบเฉพาะ ทำให้พนักงานขององค์กรสามารถเปิดพื้นที่ทำงานบน APP มือถือได้โดยไม่ต้องเข้าสู่ระบบ


รับกุญแจสาธารณะ

  1. เปิดฝั่ง Web → การจัดการพื้นที่การตั้งค่าขั้นสูงแบรนด์การผสานรวม
  2. ในส่วนการผสานรวม ให้ค้นหา กุญแจสาธารณะ แล้วคลิกเพื่อดูหรือคัดลอก
  3. หากต้องการรีเฟรชกุญแจ (พบไม่บ่อย และจะทำให้ Token ที่ออกไปแล้วทั้งหมดใช้ไม่ได้) ให้คลิก รีเซ็ต

เข้ารหัส AiToken ในฐานะพนักงานขององค์กร

ภาพรวมของขั้นตอน

ขั้นที่ 1: อีเมลสมาชิก ─── เข้ารหัส RSA (กุญแจสาธารณะ) ───► ไบต์ emailEncrypted ขั้นที่ 2: emailEncrypted ─── เข้ารหัส Base64 ───► emailRSAStr ขั้นที่ 3: ต่อสตริง {projectId}:{emailRSAStr} ขั้นที่ 4: สตริงที่ต่อกันแล้ว ─── เข้ารหัส Base64 ───► AiToken สุดท้าย
                      
                      ขั้นที่ 1: อีเมลสมาชิก ─── เข้ารหัส RSA (กุญแจสาธารณะ) ───► ไบต์ emailEncrypted
ขั้นที่ 2: emailEncrypted ─── เข้ารหัส Base64 ───► emailRSAStr
ขั้นที่ 3: ต่อสตริง {projectId}:{emailRSAStr}
ขั้นที่ 4: สตริงที่ต่อกันแล้ว ─── เข้ารหัส Base64 ───► AiToken สุดท้าย

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

พารามิเตอร์ของอัลกอริทึม

พารามิเตอร์ ค่า
อัลกอริทึม RSA RSA/ECB/PKCS1Padding (คือ RSAES-PKCS1-V1_5)
รูปแบบกุญแจสาธารณะ X.509 (SubjectPublicKeyInfo), เข้ารหัส Base64
การเข้ารหัสเอาต์พุต Base64 สองครั้ง

ตัวอย่างโค้ดการเข้ารหัส Java

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());
        }
    }
}

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

ตัวอย่างโค้ดการเข้ารหัส TypeScript

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)

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

สร้าง URL สำหรับเข้าสู่ระบบเฉพาะ

สร้าง URL สำหรับเข้าสู่ระบบเฉพาะของบัญชีพนักงานตามรูปแบบ {URLการผสานรวมพื้นที่ทำงาน}?{AiToken}:

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

                    
บล็อกโค้ดนี้ในหน้าต่างลอย

เมื่อพนักงานขององค์กรเปิด URL สำหรับเข้าสู่ระบบที่เข้ารหัสเฉพาะสำหรับอีเมลบัญชีพนักงานนั้นบน APP มือถือ ก็จะสามารถเปิดพื้นที่ทำงานที่เกี่ยวข้องได้โดยไม่ต้องเข้าสู่ระบบ


ข้อควรระวังด้านความปลอดภัย

ข้อควรระวัง คำอธิบาย
ความปลอดภัยของกุญแจสาธารณะ กุญแจสาธารณะสามารถแจกจ่ายแบบเปิดเผยได้ แต่ควรดำเนินกระบวนการออก Token ที่ฝั่งเซิร์ฟเวอร์ เพื่อหลีกเลี่ยงไม่ให้ฝั่งไคลเอนต์ถือรหัสโปรเจกต์ (project ID) โดยตรง
อายุของ Token AiToken ไม่มีแนวคิดเรื่องอายุการใช้งาน แนะนำให้ออก Token ผ่านแบ็กเอนด์ในตอนที่ต้องใช้ และไม่ให้ฝั่ง APP แคชไว้เป็นเวลานาน
การจับคู่อีเมล อีเมลใน AiToken ต้องเป็นอีเมลของสมาชิกที่มีอยู่แล้วในพื้นที่ทำงาน มิฉะนั้นจะแจ้งว่าไม่มีผู้ใช้
การผูกกับองค์กร รหัสโปรเจกต์เดียวกัน (projectId) จะสอดคล้องกับหนึ่งองค์กร และสมาชิกต้องอยู่ในองค์กรนั้น
HTTPS URL การผสานรวมต้องเข้าถึงผ่าน HTTPS เพื่อป้องกันไม่ให้ Token รั่วไหลระหว่างการส่งข้อมูล

เอกสารที่เกี่ยวข้อง