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