shadow1ng/fscan · error
oracle session key should be either 64 or 96 bytes long
Error message
oracle session key should be either 64 or 96 bytes long
What it means
finish() derives client-side session keys from the server's encrypted session key (eServerSessKey). The Oracle auth protocol defines this as either 64 bytes (AES-192) or 96 bytes (AES-256); any other length means key derivation cannot proceed, so the library rejects the authentication data before attempting decryption.
Source
Thrown at plugins/services/oracle_raw.go:1339
}
default:
err := s.readMsg(msg)
if err != nil {
return nil, err
}
if msg == 4 {
if s.hasError() {
return nil, s.oracleError()
}
return auth.finish(username, password, nego)
}
}
}
}
func (auth *oracleAuthObject) finish(username, password string, nego *oracleTCPNego) (*oracleAuthObject, error) {
if len(auth.eServerSessKey) != 64 && len(auth.eServerSessKey) != 96 {
return nil, errors.New("oracle session key should be either 64 or 96 bytes long")
}
var key []byte
var speedyKey []byte
padding := false
var err error
switch auth.verifierType {
case 2361:
key, err = oracleKeyFromUserPass(username, password)
case 6949:
if len(nego.serverCompileTimeCaps) > 4 && nego.serverCompileTimeCaps[4]&2 == 0 {
padding = true
}
salt, err := hex.DecodeString(auth.salt)
if err != nil {
return nil, err
}
h := sha1.New()
_, _ = h.Write(append([]byte(password), salt...))View on GitHub (pinned to 95cc12e753)
Solutions
- Check Oracle server crypto/NNE configuration and version against plugin-supported combinations (64 vs 96 byte keys)
- Retry and inspect whether the auth response was truncated by the network/proxy — a full 64/96-byte key may simply be missing tail bytes
- Align AUTH_PBKDF2_* parameters and verifier type between client and server (e.g. avoid forcing key size via sqlnet crypto settings)
- Log the actual session-key length and file an upstream issue if your server version legitimately uses a different size
Example fix
// before
if len(auth.eServerSessKey) != 64 && len(auth.eServerSessKey) != 96 {
return nil, errors.New("oracle session key should be either 64 or 96 bytes long")
}
// after
if len(auth.eServerSessKey) != 64 && len(auth.eServerSessKey) != 96 {
return nil, fmt.Errorf("oracle session key should be either 64 or 96 bytes long: got %d", len(auth.eServerSessKey))
} Defensive patterns
Strategy: validation
Validate before calling
// validate session-key length before deriving keys
if len(auth.eServerSessKey) != 64 && len(auth.eServerSessKey) != 96 {
return fmt.Errorf("bad server session key length: %d", len(auth.eServerSessKey))
} Type guard
func validServerSessKey(k []byte) bool { return len(k) == 64 || len(k) == 96 } Try / catch
auth, err := authObj.finish(user, pass, nego)
if err != nil && strings.Contains(err.Error(), "session key should be either 64 or 96 bytes") {
return fmt.Errorf("server sent %d-byte session key; check server crypto config and version support: %w", len(auth.eServerSessKey), err)
} Prevention
- Align server NNE/PBKDF2 crypto settings with the plugin's supported key sizes
- Rule out truncated auth responses (retry / direct connection test)
- Log the actual key length when diagnosing version mismatches
When it happens
Trigger: auth.finish(username, password, nego) is called after parsing the auth response and len(auth.eServerSessKey) is neither 64 nor 96 — typically when verifierType indicates PBKDF2/AES but the server sent a legacy or malformed session key.
Common situations: Server configured for a crypto strength the plugin's length check doesn't cover; mixed-version behavior where an older verifier type is answered with a different key size; a truncated auth response from the network.
Related errors
- oracle authentication failed
- oracle advanced authentication negotiation failed
- oracle authentication protocol internal error
- unsupported oracle authentication service %s
- unsupported oracle verifier type %d
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/c5cb0744f02c542e.
Report an issue: GitHub.