package services import ( helper "api-service/internal/helpers/bpjs" "bytes" "compress/gzip" "crypto/aes" "crypto/cipher" "crypto/sha256" "encoding/base64" "errors" "io" "log" ) func min(a, b int) int { if a < b { return a } return b } // ResponseVclaim decrypts the encrypted response from VClaim API func ResponseVclaim(encrypted string, key string) (string, error) { log.Println("ResponseVclaim: Starting decryption process") log.Printf("ResponseVclaim: Encrypted string: %s", encrypted) // Pad the base64 string if needed if len(encrypted)%4 != 0 { padding := (4 - len(encrypted)%4) % 4 for i := 0; i < padding; i++ { encrypted += "=" } log.Printf("ResponseVclaim: Padded encrypted string: %s", encrypted) } cipherText, err := base64.StdEncoding.DecodeString(encrypted) if err != nil { log.Printf("ResponseVclaim: Failed to decode base64: %v", err) return "", err } log.Printf("ResponseVclaim: Base64 decoded successfully, length: %d", len(cipherText)) hash := sha256.Sum256([]byte(key)) block, err := aes.NewCipher(hash[:]) if err != nil { log.Printf("ResponseVclaim: Failed to create AES cipher: %v", err) return "", err } if len(cipherText) < aes.BlockSize { log.Println("ResponseVclaim: CipherText too short") return "", errors.New("cipherText too short") } iv := hash[:aes.BlockSize] if len(cipherText)%aes.BlockSize != 0 { log.Println("ResponseVclaim: CipherText not multiple of block size") return "", errors.New("cipherText is not a multiple of the block size") } mode := cipher.NewCBCDecrypter(block, iv) mode.CryptBlocks(cipherText, cipherText) log.Println("ResponseVclaim: AES decryption completed") // cipherText, _ = pkcs7.Unpad(cipherText, aes.BlockSize) cipherText = helper.RemovePKCS7Padding(cipherText) log.Printf("ResponseVclaim: PKCS7 padding removed, length: %d", len(cipherText)) var data string // Try gzip decompression first reader, err := gzip.NewReader(bytes.NewReader(cipherText)) if err != nil { log.Printf("ResponseVclaim: Gzip decompression failed: %v, trying LZ-string decompression", err) // Try lz-string decompression using helper function data, err := helper.StringDecrypt(key, string(cipherText)) if err != nil || len(data) == 0 { log.Printf("ResponseVclaim: Helper StringDecrypt failed or empty: %v, trying without decompression", err) // Try without decompression data = string(cipherText) log.Printf("ResponseVclaim: Using decrypted data without decompression, data length: %d", len(data)) } else { log.Printf("ResponseVclaim: Helper StringDecrypt successful, data length: %d, data: %s", len(data), data[:min(100, len(data))]) } } else { defer reader.Close() decompressed, err := io.ReadAll(reader) if err != nil { log.Printf("ResponseVclaim: Failed to read gzip decompressed data: %v, trying LZ-string decompression", err) // Try lz-string decompression using helper function data, err := helper.StringDecrypt(key, string(cipherText)) if err != nil || len(data) == 0 { log.Printf("ResponseVclaim: Helper StringDecrypt failed or empty: %v, using data without decompression", err) data = string(cipherText) log.Printf("ResponseVclaim: Using decrypted data without decompression, data length: %d", len(data)) } else { log.Printf("ResponseVclaim: Helper StringDecrypt successful, data length: %d", len(data)) } } else { data = string(decompressed) log.Printf("ResponseVclaim: Gzip decompression successful, data length: %d", len(data)) } } log.Printf("ResponseVclaim: Final data length: %d, data: %s", len(data), data[:min(100, len(data))]) log.Println("ResponseVclaim: Decryption process completed successfully") return data, nil }