initialize static method
Initializes the global configuration (one-time).
masterKey
: ≥ 32 bytes shared secret (IKM for HKDF).salt
: optional HKDF salt (recommend random, app-wide constant).info
: optional HKDF info/context string (protocol-binding).protocolVersion
: wire-level version. Current: 1windowSeconds
: time window size (default 30).verificationSkewWindows
: how many adjacent windows to accept during verification (e.g., 1 means tryw-1, w, w+1
).timeProvider
: custom time provider; if null uses a default.
SECURITY:
- Use
forceReinitialize
only for tests or controlled rotation flows.
Implementation
static OtpCryptoConfig initialize({
required Uint8List masterKey,
Uint8List? salt,
Uint8List? info,
int protocolVersion = 1,
int windowSeconds = 30,
int verificationSkewWindows = 0,
TimeProvider? timeProvider,
bool forceReinitialize = false,
}) {
if (_instance != null && !forceReinitialize) {
throw StateError('OtpCryptoConfig is already initialized. Set forceReinitialize=true to replace (use with caution).');
}
if (masterKey.length < 32) {
throw ArgumentError.value(masterKey.length, 'masterKey.length', 'Must be at least 32 bytes.');
}
if (windowSeconds <= 0) {
throw ArgumentError.value(windowSeconds, 'windowSeconds', 'Must be a positive integer.');
}
if (verificationSkewWindows < 0 || verificationSkewWindows > 2) {
// keeping this small avoids costly re-MAC attempts; tune as needed
throw ArgumentError.value(verificationSkewWindows, 'verificationSkewWindows', 'Must be between 0 and 2.');
}
final cfg = OtpCryptoConfig._(
protocolVersion: protocolVersion,
windowSeconds: windowSeconds,
verificationSkewWindows: verificationSkewWindows,
masterKey: _copy(masterKey),
hkdfSalt: salt != null ? _copy(salt) : null,
hkdfInfo: info != null ? _copy(info) : null,
timeProvider: timeProvider ?? _DefaultSystemTimeProvider(),
);
_instance = cfg;
return cfg;
}