mirror of
https://github.com/moparisthebest/keepass2android
synced 2024-12-22 23:18:48 -05:00
-Added support for variable length challenges
-New "lt64" field in xml file handled properly -KeeChallengeProv is no longer a static class but object oriented
This commit is contained in:
parent
8779c90da9
commit
f91a15e03c
@ -31,6 +31,8 @@ namespace KeeChallenge
|
||||
{
|
||||
public class ChallengeInfo
|
||||
{
|
||||
private bool m_LT64;
|
||||
|
||||
public byte[] EncryptedSecret {
|
||||
get;
|
||||
private set;
|
||||
@ -51,16 +53,24 @@ namespace KeeChallenge
|
||||
private set;
|
||||
}
|
||||
|
||||
private ChallengeInfo()
|
||||
public bool LT64
|
||||
{
|
||||
get { return m_LT64; }
|
||||
private set { m_LT64 = value; }
|
||||
}
|
||||
|
||||
public ChallengeInfo(byte[] encryptedSecret, byte[] iv, byte[] challenge, byte[] verification)
|
||||
private ChallengeInfo()
|
||||
{
|
||||
LT64 = false;
|
||||
}
|
||||
|
||||
public ChallengeInfo(byte[] encryptedSecret, byte[] iv, byte[] challenge, byte[] verification, bool lt64)
|
||||
{
|
||||
EncryptedSecret = encryptedSecret;
|
||||
IV = iv;
|
||||
Challenge = challenge;
|
||||
Verification = verification;
|
||||
LT64 = lt64;
|
||||
}
|
||||
|
||||
public static ChallengeInfo Load(IOConnectionInfo ioc)
|
||||
@ -125,6 +135,10 @@ namespace KeeChallenge
|
||||
xml.Read();
|
||||
Verification = Convert.FromBase64String(xml.Value.Trim());
|
||||
break;
|
||||
case "lt64":
|
||||
xml.Read();
|
||||
if (!bool.TryParse(xml.Value.Trim(), out m_LT64)) throw new Exception("Unable to parse LT64 flag");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -184,6 +198,7 @@ namespace KeeChallenge
|
||||
|
||||
xml.WriteElementString("challenge", Convert.ToBase64String(Challenge));
|
||||
xml.WriteElementString("verification", Convert.ToBase64String(Verification));
|
||||
xml.WriteElementString("lt64", LT64.ToString());
|
||||
|
||||
xml.WriteEndElement();
|
||||
xml.WriteEndDocument();
|
||||
|
@ -46,19 +46,40 @@ namespace KeeChallenge
|
||||
public const int responseLenBytes = 20;
|
||||
public const int secretLenBytes = 20;
|
||||
|
||||
private KeeChallengeProv()
|
||||
//If variable length challenges are enabled, a 63 byte challenge is sent instead.
|
||||
//See GenerateChallenge() and http://forum.yubico.com/viewtopic.php?f=16&t=1078
|
||||
//This field is automatically set by calling GetSecret(). However, when creating
|
||||
//a new database it will need to be set manually based on the user's yubikey settings
|
||||
public bool LT64
|
||||
{
|
||||
}
|
||||
|
||||
private static byte[] GenerateChallenge()
|
||||
{
|
||||
CryptoRandom rand = CryptoRandom.Instance;
|
||||
return CryptoRandom.Instance.GetRandomBytes(challengeLenBytes);
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private static byte[] GenerateResponse(byte[] challenge, byte[] key)
|
||||
private KeeChallengeProv()
|
||||
{
|
||||
LT64 = false;
|
||||
}
|
||||
|
||||
private byte[] GenerateChallenge()
|
||||
{
|
||||
CryptoRandom rand = CryptoRandom.Instance;
|
||||
byte[] chal = CryptoRandom.Instance.GetRandomBytes(challengeLenBytes);
|
||||
if (LT64)
|
||||
{
|
||||
chal[challengeLenBytes - 2] = (byte)~chal[challengeLenBytes - 1];
|
||||
}
|
||||
|
||||
return chal;
|
||||
}
|
||||
|
||||
private byte[] GenerateResponse(byte[] challenge, byte[] key)
|
||||
{
|
||||
HMACSHA1 hmac = new HMACSHA1(key);
|
||||
|
||||
if (LT64)
|
||||
challenge = challenge.Take(challengeLenBytes - 1).ToArray();
|
||||
|
||||
byte[] resp = hmac.ComputeHash(challenge);
|
||||
hmac.Clear();
|
||||
return resp;
|
||||
@ -71,7 +92,7 @@ namespace KeeChallenge
|
||||
/// </summary>
|
||||
/// <param name="secret">The un-encrypted secret</param>
|
||||
/// <returns>A fully populated ChallengeInfo object ready to be saved</returns>
|
||||
public static ChallengeInfo Encrypt(byte[] secret)
|
||||
public ChallengeInfo Encrypt(byte[] secret)
|
||||
{
|
||||
//generate a random challenge for use next time
|
||||
byte[] challenge = GenerateChallenge();
|
||||
@ -101,14 +122,14 @@ namespace KeeChallenge
|
||||
msEncrypt.Close();
|
||||
}
|
||||
|
||||
ChallengeInfo inf = new ChallengeInfo (encrypted, IV, challenge, secretHash);
|
||||
ChallengeInfo inf = new ChallengeInfo (encrypted, IV, challenge, secretHash, LT64);
|
||||
|
||||
sha.Clear();
|
||||
|
||||
return inf;
|
||||
}
|
||||
|
||||
private static bool DecryptSecret(byte[] yubiResp, ChallengeInfo inf, out byte[] secret)
|
||||
private bool DecryptSecret(byte[] yubiResp, ChallengeInfo inf, out byte[] secret)
|
||||
{
|
||||
secret = new byte[keyLenBytes];
|
||||
|
||||
@ -156,7 +177,7 @@ namespace KeeChallenge
|
||||
/// This should be populated from the database.xml auxilliary file</param>
|
||||
/// <param name="resp" >The Yubikey's response to the issued challenge</param>
|
||||
/// <returns>The common secret, used as a composite key to encrypt a Keepass database</returns>
|
||||
public static byte[] GetSecret(ChallengeInfo inf, byte[] resp)
|
||||
public byte[] GetSecret(ChallengeInfo inf, byte[] resp)
|
||||
{
|
||||
if (resp.Length != responseLenBytes)
|
||||
return null;
|
||||
@ -165,6 +186,8 @@ namespace KeeChallenge
|
||||
if (inf.Challenge == null ||
|
||||
inf.Verification == null)
|
||||
return null;
|
||||
|
||||
LT64 = inf.LT64;
|
||||
|
||||
byte[] secret;
|
||||
|
||||
|
@ -129,6 +129,7 @@ namespace keepass2android
|
||||
private OtpInfo _otpInfo;
|
||||
private ChallengeInfo _chalInfo;
|
||||
private byte[] _challengeSecret;
|
||||
private KeeChallengeProv _challengeProv;
|
||||
private readonly int[] _otpTextViewIds = new[] {Resource.Id.otp1, Resource.Id.otp2, Resource.Id.otp3, Resource.Id.otp4, Resource.Id.otp5, Resource.Id.otp6};
|
||||
private const string OtpInfoKey = "OtpInfoKey";
|
||||
private const string EnteredOtpsKey = "EnteredOtpsKey";
|
||||
@ -325,8 +326,9 @@ namespace keepass2android
|
||||
{
|
||||
try
|
||||
{
|
||||
_challengeProv = new KeeChallengeProv();
|
||||
byte[] challengeResponse = data.GetByteArrayExtra("response");
|
||||
_challengeSecret = KeeChallengeProv.GetSecret(_chalInfo, challengeResponse);
|
||||
_challengeSecret = _challengeProv.GetSecret(_chalInfo, challengeResponse);
|
||||
Array.Clear(challengeResponse, 0, challengeResponse.Length);
|
||||
}
|
||||
catch (Exception e)
|
||||
@ -348,7 +350,7 @@ namespace keepass2android
|
||||
//save aux file
|
||||
try
|
||||
{
|
||||
ChallengeInfo temp = KeeChallengeProv.Encrypt(_challengeSecret);
|
||||
ChallengeInfo temp = _challengeProv.Encrypt(_challengeSecret);
|
||||
IFileStorage fileStorage = App.Kp2a.GetOtpAuxFileStorage(_ioConnection);
|
||||
IOConnectionInfo iocAux = fileStorage.GetFilePath(fileStorage.GetParentPath(_ioConnection),
|
||||
fileStorage.GetFilenameWithoutPathAndExt(_ioConnection) + ".xml");
|
||||
|
Loading…
Reference in New Issue
Block a user