Intial commit
This commit is contained in:
commit
33a1762896
37
otpnet/LICENSE.txt
Normal file
37
otpnet/LICENSE.txt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
OTPNet is licensed under the terms of Apache 2.0
|
||||||
|
|
||||||
|
Copyright [2012] [Nathan Adams]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
This project was based off of OTPHP (https://github.com/lelag/otphp) by Le Lag
|
||||||
|
|
||||||
|
Copyright (c) 2011 Le Lag
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
132
otpnet/Libraries/Base32Encoding.cs
Normal file
132
otpnet/Libraries/Base32Encoding.cs
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
// http://stackoverflow.com/a/7135008/195722
|
||||||
|
public class Base32Encoding
|
||||||
|
{
|
||||||
|
public static byte[] ToBytes(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("input");
|
||||||
|
}
|
||||||
|
|
||||||
|
input = input.TrimEnd('='); //remove padding characters
|
||||||
|
int byteCount = input.Length * 5 / 8; //this must be TRUNCATED
|
||||||
|
byte[] returnArray = new byte[byteCount];
|
||||||
|
|
||||||
|
byte curByte = 0, bitsRemaining = 8;
|
||||||
|
int mask = 0, arrayIndex = 0;
|
||||||
|
|
||||||
|
foreach (char c in input)
|
||||||
|
{
|
||||||
|
int cValue = CharToValue(c);
|
||||||
|
|
||||||
|
if (bitsRemaining > 5)
|
||||||
|
{
|
||||||
|
mask = cValue << (bitsRemaining - 5);
|
||||||
|
curByte = (byte)(curByte | mask);
|
||||||
|
bitsRemaining -= 5;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = cValue >> (5 - bitsRemaining);
|
||||||
|
curByte = (byte)(curByte | mask);
|
||||||
|
returnArray[arrayIndex++] = curByte;
|
||||||
|
curByte = (byte)(cValue << (3 + bitsRemaining));
|
||||||
|
bitsRemaining += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we didn't end with a full byte
|
||||||
|
if (arrayIndex != byteCount)
|
||||||
|
{
|
||||||
|
returnArray[arrayIndex] = curByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(byte[] input)
|
||||||
|
{
|
||||||
|
if (input == null || input.Length == 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("input");
|
||||||
|
}
|
||||||
|
|
||||||
|
int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;
|
||||||
|
char[] returnArray = new char[charCount];
|
||||||
|
|
||||||
|
byte nextChar = 0, bitsRemaining = 5;
|
||||||
|
int arrayIndex = 0;
|
||||||
|
|
||||||
|
foreach (byte b in input)
|
||||||
|
{
|
||||||
|
nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));
|
||||||
|
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||||
|
|
||||||
|
if (bitsRemaining < 4)
|
||||||
|
{
|
||||||
|
nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);
|
||||||
|
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||||
|
bitsRemaining += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitsRemaining -= 3;
|
||||||
|
nextChar = (byte)((b << bitsRemaining) & 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
//if we didn't end with a full char
|
||||||
|
if (arrayIndex != charCount)
|
||||||
|
{
|
||||||
|
returnArray[arrayIndex++] = ValueToChar(nextChar);
|
||||||
|
while (arrayIndex != charCount) returnArray[arrayIndex++] = '='; //padding
|
||||||
|
}
|
||||||
|
|
||||||
|
return new string(returnArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CharToValue(char c)
|
||||||
|
{
|
||||||
|
int value = (int)c;
|
||||||
|
|
||||||
|
//65-90 == uppercase letters
|
||||||
|
if (value < 91 && value > 64)
|
||||||
|
{
|
||||||
|
return value - 65;
|
||||||
|
}
|
||||||
|
//50-55 == numbers 2-7
|
||||||
|
if (value < 56 && value > 49)
|
||||||
|
{
|
||||||
|
return value - 24;
|
||||||
|
}
|
||||||
|
//97-122 == lowercase letters
|
||||||
|
if (value < 123 && value > 96)
|
||||||
|
{
|
||||||
|
return value - 97;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException("Character is not a Base32 character.", "c");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char ValueToChar(byte b)
|
||||||
|
{
|
||||||
|
if (b < 26)
|
||||||
|
{
|
||||||
|
return (char)(b + 65);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b < 32)
|
||||||
|
{
|
||||||
|
return (char)(b + 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentException("Byte is not a value Base32 value.", "b");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
45
otpnet/Libraries/StringExtensions.cs
Normal file
45
otpnet/Libraries/StringExtensions.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
/// <summary>Returns a string array that contains the substrings in this string that are seperated a given fixed length.</summary>
|
||||||
|
/// <param name="s">This string object.</param>
|
||||||
|
/// <param name="length">Size of each substring.
|
||||||
|
/// <para>CASE: length > 0 , RESULT: String is split from left to right.</para>
|
||||||
|
/// <para>CASE: length == 0 , RESULT: String is returned as the only entry in the array.</para>
|
||||||
|
/// <para>CASE: length < 0 , RESULT: String is split from right to left.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>String array that has been split into substrings of equal length.</returns>
|
||||||
|
/// <example>
|
||||||
|
/// <code>
|
||||||
|
/// string s = "1234567890";
|
||||||
|
/// string[] a = s.Split(4); // a == { "1234", "5678", "90" }
|
||||||
|
/// </code>
|
||||||
|
/// </example>
|
||||||
|
public static string[] Split(this string s, int length)
|
||||||
|
{
|
||||||
|
System.Globalization.StringInfo str = new System.Globalization.StringInfo(s);
|
||||||
|
|
||||||
|
int lengthAbs = Math.Abs(length);
|
||||||
|
|
||||||
|
if (str == null || str.LengthInTextElements == 0 || lengthAbs == 0 || str.LengthInTextElements <= lengthAbs)
|
||||||
|
return new string[] { str.ToString() };
|
||||||
|
|
||||||
|
string[] array = new string[(str.LengthInTextElements % lengthAbs == 0 ? str.LengthInTextElements / lengthAbs : (str.LengthInTextElements / lengthAbs) + 1)];
|
||||||
|
|
||||||
|
if (length > 0)
|
||||||
|
for (int iStr = 0, iArray = 0; iStr < str.LengthInTextElements && iArray < array.Length; iStr += lengthAbs, iArray++)
|
||||||
|
array[iArray] = str.SubstringByTextElements(iStr, (str.LengthInTextElements - iStr < lengthAbs ? str.LengthInTextElements - iStr : lengthAbs));
|
||||||
|
else // if (length < 0)
|
||||||
|
for (int iStr = str.LengthInTextElements - 1, iArray = array.Length - 1; iStr >= 0 && iArray >= 0; iStr -= lengthAbs, iArray--)
|
||||||
|
array[iArray] = str.SubstringByTextElements((iStr - lengthAbs < 0 ? 0 : iStr - lengthAbs + 1), (iStr - lengthAbs < 0 ? iStr + 1 : lengthAbs));
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
otpnet/Libraries/Unixtime.cs
Normal file
35
otpnet/Libraries/Unixtime.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
class Unixtime
|
||||||
|
{
|
||||||
|
private DateTime date;
|
||||||
|
|
||||||
|
public Unixtime()
|
||||||
|
{
|
||||||
|
this.date = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unixtime(int timestamp)
|
||||||
|
{
|
||||||
|
DateTime converted = new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||||
|
DateTime newDateTime = converted.AddSeconds(timestamp);
|
||||||
|
this.date = newDateTime.ToLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime toDateTime()
|
||||||
|
{
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long toTimeStamp()
|
||||||
|
{
|
||||||
|
TimeSpan span = (this.date - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToLocalTime());
|
||||||
|
return Convert.ToInt64(span.TotalSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
otpnet/OTP/HOTP.cs
Normal file
58
otpnet/OTP/HOTP.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* HOTP - One time password generator
|
||||||
|
*
|
||||||
|
* The HOTP class allow for the generation
|
||||||
|
* and verification of one-time password using
|
||||||
|
* the HOTP specified algorithm.
|
||||||
|
*
|
||||||
|
* This class is meant to be compatible with
|
||||||
|
* Google Authenticator
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
public class HOTP : OTP
|
||||||
|
{
|
||||||
|
|
||||||
|
public HOTP(string secret)
|
||||||
|
: base(secret, 6, HashAlgorithm.SHA1)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password for a specific counter value
|
||||||
|
* @param integer $count the counter which is used to
|
||||||
|
* seed the hmac hash function.
|
||||||
|
* @return integer the One Time Password
|
||||||
|
*/
|
||||||
|
public int at(int count)
|
||||||
|
{
|
||||||
|
return this.generateOTP(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if a password is valid for a specific counter value
|
||||||
|
*
|
||||||
|
* @param integer $otp the one-time password
|
||||||
|
* @param integer $counter the counter value
|
||||||
|
* @return bool true if the counter is valid, false otherwise
|
||||||
|
*/
|
||||||
|
public bool verify(int otp, int counter)
|
||||||
|
{
|
||||||
|
return (otp == this.at(counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string provisioning_uri(string name, int initial_count)
|
||||||
|
{
|
||||||
|
return "otpauth://hotp/" + name + "?secret=" + this.secret + " &counter=" + initial_count.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
147
otpnet/OTP/OTP.cs
Normal file
147
otpnet/OTP/OTP.cs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
|
||||||
|
// Please see LICENSE.txt for information on what license this is released under
|
||||||
|
public enum HashAlgorithm
|
||||||
|
{
|
||||||
|
SHA1
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class was ported from this PHP library https://github.com/lelag/otphp which was ported from a Ruby library
|
||||||
|
/**
|
||||||
|
* One Time Password Generator
|
||||||
|
*
|
||||||
|
* The OTP class allow the generation of one-time
|
||||||
|
* password that is described in rfc 4xxx.
|
||||||
|
*
|
||||||
|
* This is class is meant to be compatible with
|
||||||
|
* Google Authenticator.
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
public class OTP
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The base32 encoded secret key
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The algorithm used for the hmac hash function
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public HashAlgorithm digest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of digits in the one-time password
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public int digits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the OTP class
|
||||||
|
* @param string $secret the secret key
|
||||||
|
* @param array $opt options array can contain the
|
||||||
|
* following keys :
|
||||||
|
* @param integer digits : the number of digits in the one time password
|
||||||
|
* Currently Google Authenticator only support 6. Defaults to 6.
|
||||||
|
* @param string digest : the algorithm used for the hmac hash function
|
||||||
|
* Google Authenticator only support sha1. Defaults to sha1
|
||||||
|
*
|
||||||
|
* @return new OTP class.
|
||||||
|
*/
|
||||||
|
public OTP(string secret)
|
||||||
|
{
|
||||||
|
this.secret = secret;
|
||||||
|
this.digits = 6;
|
||||||
|
this.digest = HashAlgorithm.SHA1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OTP(string secret, int digits)
|
||||||
|
{
|
||||||
|
this.digits = digits;
|
||||||
|
this.digest = HashAlgorithm.SHA1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OTP(string secret, int digits, HashAlgorithm digest)
|
||||||
|
{
|
||||||
|
this.secret = secret;
|
||||||
|
this.digits = digits;
|
||||||
|
this.digest = digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a one-time password
|
||||||
|
*
|
||||||
|
* @param integer $input : number used to seed the hmac hash function.
|
||||||
|
* This number is usually a counter (HOTP) or calculated based on the current
|
||||||
|
* timestamp (see TOTP class).
|
||||||
|
* @return integer the one-time password
|
||||||
|
*/
|
||||||
|
public int generateOTP(Int64 input)
|
||||||
|
{
|
||||||
|
|
||||||
|
HMAC hashgenerator = null;
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case HashAlgorithm.SHA1:
|
||||||
|
hashgenerator = new HMACSHA1(Base32Encoding.ToBytes(secret));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hashgenerator.ComputeHash(intToByteString(input));
|
||||||
|
string hash = "";
|
||||||
|
|
||||||
|
foreach(byte b in hashgenerator.Hash)
|
||||||
|
{
|
||||||
|
hash += b.ToString("x2");
|
||||||
|
}
|
||||||
|
List<int> hmac = new List<int>();
|
||||||
|
foreach (string s in hash.Split(2))
|
||||||
|
{
|
||||||
|
hmac.Add(Int32.Parse(s, System.Globalization.NumberStyles.HexNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = hmac[19] & 0xf;
|
||||||
|
int code = (hmac[offset + 0] & 0x7F) << 24 |
|
||||||
|
(hmac[offset + 1] & 0xFF) << 16 |
|
||||||
|
(hmac[offset + 2] & 0xFF) << 8 |
|
||||||
|
(hmac[offset + 3] & 0xFF);
|
||||||
|
|
||||||
|
return code % (int)Math.Pow((double)10, (double)this.digits);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] intToByteString(Int64 i)
|
||||||
|
{
|
||||||
|
List<byte> res = new List<byte>();
|
||||||
|
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
res.Add((byte)(i & 0xFF));
|
||||||
|
i >>= 8;
|
||||||
|
}
|
||||||
|
int rcount = res.Count;
|
||||||
|
for (int z = 0; z < 8 - rcount; z++)
|
||||||
|
res.Add((byte)0);
|
||||||
|
res.Reverse();
|
||||||
|
|
||||||
|
return res.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
120
otpnet/OTP/TOTP.cs
Normal file
120
otpnet/OTP/TOTP.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OTPNet
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* TOTP - One time password generator
|
||||||
|
*
|
||||||
|
* The TOTP class allow for the generation
|
||||||
|
* and verification of one-time password using
|
||||||
|
* the TOTP specified algorithm.
|
||||||
|
*
|
||||||
|
* This class is meant to be compatible with
|
||||||
|
* Google Authenticator
|
||||||
|
*
|
||||||
|
* This class was originally ported from the rotp
|
||||||
|
* ruby library available at https://github.com/mdp/rotp
|
||||||
|
*/
|
||||||
|
public class TOTP : OTP
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval in seconds for a one-time password timeframe
|
||||||
|
* Defaults to 30
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
public double interval;
|
||||||
|
|
||||||
|
|
||||||
|
public TOTP(string secret)
|
||||||
|
: base(secret, 6, HashAlgorithm.SHA1)
|
||||||
|
{
|
||||||
|
this.interval = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TOTP(string secret, double interval)
|
||||||
|
: base(secret, 6, HashAlgorithm.SHA1)
|
||||||
|
{
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TOTP(string secret, double interval, int digits)
|
||||||
|
: base(secret, digits, HashAlgorithm.SHA1)
|
||||||
|
{
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TOTP(string secret, double interval, int digits, HashAlgorithm algo)
|
||||||
|
: base(secret, digits, algo)
|
||||||
|
{
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password for a specific timestamp value
|
||||||
|
*
|
||||||
|
* @param integer $timestamp the timestamp which is timecoded and
|
||||||
|
* used to seed the hmac hash function.
|
||||||
|
* @return integer the One Time Password
|
||||||
|
*/
|
||||||
|
public int at(double timestamp)
|
||||||
|
{
|
||||||
|
return this.generateOTP(this.timecode(timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password for the current timestamp value
|
||||||
|
*
|
||||||
|
* @return integer the current One Time Password
|
||||||
|
*/
|
||||||
|
public int now()
|
||||||
|
{
|
||||||
|
return this.at(new Unixtime().toTimeStamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if a password is valid for a specific counter value
|
||||||
|
*
|
||||||
|
* @param integer $otp the one-time password
|
||||||
|
* @param integer $timestamp the timestamp for the a given time, defaults to current time.
|
||||||
|
* @return bool true if the counter is valid, false otherwise
|
||||||
|
*/
|
||||||
|
public bool verify(int otp, double timestamp)
|
||||||
|
{
|
||||||
|
return (otp == this.at(timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool verify(int otp)
|
||||||
|
{
|
||||||
|
//calls verify(int, int)
|
||||||
|
return this.verify(otp, new Unixtime().toTimeStamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the uri for a specific secret for totp method.
|
||||||
|
* Can be encoded as a image for simple configuration in
|
||||||
|
* Google Authenticator.
|
||||||
|
*
|
||||||
|
* @param string $name the name of the account / profile
|
||||||
|
* @return string the uri for the hmac secret
|
||||||
|
*/
|
||||||
|
public string provisitioning_uri(string name)
|
||||||
|
{
|
||||||
|
return "otpauth://totp/" + name + "?secret=" + this.secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a timestamp in a counter based on specified internal
|
||||||
|
*
|
||||||
|
* @param integer $timestamp
|
||||||
|
* @return integer the timecode
|
||||||
|
*/
|
||||||
|
public Int64 timecode(double timestamp)
|
||||||
|
{
|
||||||
|
return (Int64)(((((timestamp * 1000)) / (this.interval * 1000))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
otpnet/OTPNet.csproj
Normal file
59
otpnet/OTPNet.csproj
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{F1FD321D-6F2A-4431-8307-6BF959419DBE}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>OTPNet</RootNamespace>
|
||||||
|
<AssemblyName>OTPNet</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Libraries\Base32Encoding.cs" />
|
||||||
|
<Compile Include="OTP\HOTP.cs" />
|
||||||
|
<Compile Include="OTP\OTP.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Libraries\StringExtensions.cs" />
|
||||||
|
<Compile Include="OTP\TOTP.cs" />
|
||||||
|
<Compile Include="Libraries\Unixtime.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
20
otpnet/OTPNet.sln
Normal file
20
otpnet/OTPNet.sln
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OTPNet", "OTPNet.csproj", "{F1FD321D-6F2A-4431-8307-6BF959419DBE}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{F1FD321D-6F2A-4431-8307-6BF959419DBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F1FD321D-6F2A-4431-8307-6BF959419DBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F1FD321D-6F2A-4431-8307-6BF959419DBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F1FD321D-6F2A-4431-8307-6BF959419DBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
36
otpnet/Properties/AssemblyInfo.cs
Normal file
36
otpnet/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("OTPNet")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("OTPNet")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("ff624b9a-844a-4ede-9cdd-87025ddd4201")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
Loading…
Reference in New Issue
Block a user