private bool ResyncCheck(ref Device devices, string[] codes, long counter) { for (int i = 0; i < codes.Length; i++) { string code = Generate(Decrypt(devices.Key), counter + i); if (code != codes[i]) return false; } return true; }
internal bool TryGet(string ident, out Device devices) { devices = null; if (ident == null) return false; foreach (var d in _db) { if (d.Ident != ident) continue; devices = d; return true; } //devices not found, returning false. return false; }
internal bool HasMaxFailures(ref Device devices) { if (MaxAttempts == 0 || devices.Failures < MaxAttempts) return false; devices.Failures++; return true; }
/// <summary> /// Resyncs a remote devices with the local devices database. /// You can enter multiple codes, for the resync to succeed, all the /// codes need to be verified. Its more secure to use multiple codes. /// /// If is successfully syncs it use the call back for you to unlock the /// device and set the correct counter. /// </summary> ///<param name="device">device that you want to resync</param> ///<param name="codes">list of codes that should be verified</param> ///<param name="counter">start counter, meaning on what interval should se start resync'ing</param> ///<param name="updateDevice">call back delegate for when the resync was successfull, we need to update the device differently depending on HOTP/TOTP</param> ///<param name="window">overrides global window for the resync. Set to -1 to use the default window</param> ///<exception cref="ArgumentNullException">If codes or ident is null</exception> ///<exception cref="ArgumentOutOfRangeException">If window is less than -1</exception> /// <exception cref="OtpDecryptionException">if key failed to decrypt</exception> ///<returns>true if resync was successfull</returns> /// <remarks> /// Background info (RFC4226): /// As we suggested for the resynchronization to enter a short sequence /// (say, 2 or 3) of HOTP values, we could generalize the concept to the /// protocol, and add a parameter L that would define the length of the /// HOTP sequence to enter. /// /// Per default, the value L SHOULD be set to 1, but if security needs to /// be increased, users might be asked (possibly for a short period of /// time, or a specific operation) to enter L HOTP values. /// /// This is another way, without increasing the HOTP length or using /// alphanumeric values to tighten security. /// /// Note: The system MAY also be programmed to request synchronization on /// a regular basis (e.g., every night, twice a week, etc.) and to /// achieve this purpose, ask for a sequence of L HOTP values. /// </remarks> internal bool Resync(Device device, string[] codes, long counter, UpdateDevice updateDevice, int window = -1) { for (int i = 0; i <= window; i++) { //check forward in totp/hotp counter if (Generate(Decrypt(device.Key), counter + i) == codes[0] && ResyncCheck(ref device, codes, counter + i)) { updateDevice(ref device, counter + i + codes.Length); //delegate to update devices. return true; } //check backwards in totp/hotp counter if (Generate(Decrypt(device.Key), counter - i) == codes[0] && ResyncCheck(ref device, codes, counter - i)) { updateDevice(ref device, counter - i + codes.Length); //delegate to update devices. return true; } } return false; }
internal void DoThrottling(ref Device devices) { if (devices.Failures == 0 || !EnableThrottling) return; Thread.Sleep(ThrottlingDelay * devices.Failures); }
private VerifyResult UpdateDevice(ref Device devices, int newOffset, long currentCounter) { if (CheckUsedCounter(ref devices, newOffset + currentCounter)) return VerifyResult.FailedUsedCode; devices.TotpOffset = newOffset; //set offset from devices + the current offset. devices.Failures = 0; return VerifyResult.Success; }
private void UpdateDevice(ref Device devices, long counter) { devices.TotpOffset = (int) (counter - GetCurrentTimeInterval(TimeStep)); devices.Failures = 0; devices.TotpUsedCounter = new List<long>(); }
private bool CheckUsedCounter(ref Device devices, long counter) { if (devices.TotpUsedCounter == null) devices.TotpUsedCounter = new List<long>(); //make sure we can only use a counter once. if (devices.TotpUsedCounter.Contains(counter)) { devices.Failures++; return true; } devices.TotpUsedCounter.Add(counter); return false; }
private static void UpdateDevice(ref Device devices, long counter) { devices.HotpCounter = counter; devices.Failures = 0; }