-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:
		| @@ -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"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 brush701
					brush701