The 1.4.2 extension replaced the old signed/encrypted chat gateway with an
OpenAI-compatible aigateway. Align the proxy with the new flow:
- Use ecloud.10086.cn login/model base URLs, zhanlu_ide plugin headers and
v1.4.2 plugin version
- Provision the model API key via SM2-signed get-or-create after v1/login
profile fetch; store api_key/model_base_url/email in credentials
- Chat via Bearer apiKey against {modelBaseUrl}/chat/completions with plain
OpenAI SSE passthrough; fetch /v1/models from the gateway model-info endpoint
- Force HTTP/1.1 upstream (gateway drops HTTP/2 ALPN negotiation with EOF)
- Drop obsolete AES body encryption, model name mapping and vscode headers
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
func DecryptCredential(ciphertextBase64, key string) (string, error) {
|
|
ciphertext, err := base64.StdEncoding.DecodeString(ciphertextBase64)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if len(ciphertext) == 0 || len(ciphertext)%aes.BlockSize != 0 {
|
|
return "", errors.New("invalid AES ciphertext length")
|
|
}
|
|
|
|
block, err := aes.NewCipher(repeatKey(key, aes.BlockSize))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
plain := make([]byte, len(ciphertext))
|
|
for start := 0; start < len(ciphertext); start += aes.BlockSize {
|
|
block.Decrypt(plain[start:start+aes.BlockSize], ciphertext[start:start+aes.BlockSize])
|
|
}
|
|
|
|
plain, err = unpadPKCS7(plain, aes.BlockSize)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(plain), nil
|
|
}
|
|
|
|
// DecryptCredentialOrRaw mirrors the plugin's z4A: try AES-ECB decrypt with the
|
|
// given key, falling back to the raw value when the field is plaintext.
|
|
func DecryptCredentialOrRaw(value, key string) string {
|
|
if value == "" {
|
|
return ""
|
|
}
|
|
if plain, err := DecryptCredential(value, key); err == nil && plain != "" {
|
|
return plain
|
|
}
|
|
return value
|
|
}
|
|
|
|
func repeatKey(key string, size int) []byte {
|
|
src := []byte(key)
|
|
out := make([]byte, size)
|
|
if len(src) == 0 {
|
|
return out
|
|
}
|
|
for i := range out {
|
|
out[i] = src[i%len(src)]
|
|
}
|
|
return out
|
|
}
|
|
|
|
func unpadPKCS7(in []byte, blockSize int) ([]byte, error) {
|
|
if len(in) == 0 || len(in)%blockSize != 0 {
|
|
return nil, errors.New("invalid padded data length")
|
|
}
|
|
pad := int(in[len(in)-1])
|
|
if pad == 0 || pad > blockSize || pad > len(in) {
|
|
return nil, fmt.Errorf("invalid padding size %d", pad)
|
|
}
|
|
for _, b := range in[len(in)-pad:] {
|
|
if int(b) != pad {
|
|
return nil, errors.New("invalid padding bytes")
|
|
}
|
|
}
|
|
return in[:len(in)-pad], nil
|
|
}
|