implemented loading of files with KeepassXC Challenge (#4).
requires write support, handling of Challenge/Response errors (or user cancels). Caution: saving corrupts the file at the moment!
This commit is contained in:
		| @@ -55,7 +55,10 @@ namespace KeePassLib.Cryptography.KeyDerivation | |||||||
| 			get { return "AES-KDF"; } | 			get { return "AES-KDF"; } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public AesKdf() |         public override byte[] GetSeed(KdfParameters p) | ||||||
|  |         { return p.GetByteArray(ParamSeed); } | ||||||
|  |  | ||||||
|  |         public AesKdf() | ||||||
| 		{ | 		{ | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,7 +68,10 @@ namespace KeePassLib.Cryptography.KeyDerivation | |||||||
| 			get { return "Argon2"; } | 			get { return "Argon2"; } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public Argon2Kdf() |         public override byte[] GetSeed(KdfParameters p) | ||||||
|  |         { return p.GetByteArray(ParamSalt); } | ||||||
|  |  | ||||||
|  |         public Argon2Kdf() | ||||||
| 		{ | 		{ | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -36,7 +36,9 @@ namespace KeePassLib.Cryptography.KeyDerivation | |||||||
| 			get; | 			get; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		public virtual KdfParameters GetDefaultParameters() |         public abstract byte[] GetSeed(KdfParameters p); | ||||||
|  |  | ||||||
|  |         public virtual KdfParameters GetDefaultParameters() | ||||||
| 		{ | 		{ | ||||||
| 			return new KdfParameters(this.Uuid); | 			return new KdfParameters(this.Uuid); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -20,11 +20,8 @@ | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
| using System.Text; |  | ||||||
|  |  | ||||||
| using KeePassLib.Cryptography; | using KeePassLib.Cryptography; | ||||||
| using KeePassLib.Cryptography.KeyDerivation; | using KeePassLib.Cryptography.KeyDerivation; | ||||||
| using KeePassLib.Native; |  | ||||||
| using KeePassLib.Resources; | using KeePassLib.Resources; | ||||||
| using KeePassLib.Security; | using KeePassLib.Security; | ||||||
| using KeePassLib.Utility; | using KeePassLib.Utility; | ||||||
| @@ -168,7 +165,7 @@ namespace KeePassLib.Keys | |||||||
| 		/// Creates the composite key from the supplied user key sources (password, | 		/// Creates the composite key from the supplied user key sources (password, | ||||||
| 		/// key file, user account, computer ID, etc.). | 		/// key file, user account, computer ID, etc.). | ||||||
| 		/// </summary> | 		/// </summary> | ||||||
| 		private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed) | 		private byte[] CreateRawCompositeKey32(byte[] mPbMasterSeed, byte[] mPbKdfSeed) | ||||||
| 		{ | 		{ | ||||||
| 			ValidateUserKeys(); | 			ValidateUserKeys(); | ||||||
|  |  | ||||||
| @@ -178,7 +175,7 @@ namespace KeePassLib.Keys | |||||||
| 			foreach(IUserKey pKey in m_vUserKeys) | 			foreach(IUserKey pKey in m_vUserKeys) | ||||||
| 			{ | 			{ | ||||||
| 				if (pKey is ISeedBasedUserKey) | 				if (pKey is ISeedBasedUserKey) | ||||||
| 					((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed); | 					((ISeedBasedUserKey)pKey).SetParams(mPbMasterSeed, mPbKdfSeed); | ||||||
| 				ProtectedBinary b = pKey.KeyData; | 				ProtectedBinary b = pKey.KeyData; | ||||||
| 				if(b != null) | 				if(b != null) | ||||||
| 				{ | 				{ | ||||||
| @@ -211,15 +208,17 @@ namespace KeePassLib.Keys | |||||||
| 		{ | 		{ | ||||||
| 			if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); } | 			if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); } | ||||||
|  |  | ||||||
| 			byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed); |  | ||||||
|  | 		    KdfEngine kdf = KdfPool.Get(p.KdfUuid); | ||||||
|  | 		    if (kdf == null) // CryptographicExceptions are translated to "file corrupted" | ||||||
|  | 		        throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph + | ||||||
|  | 		                            KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph + | ||||||
|  | 		                            "UUID: " + p.KdfUuid.ToHexString() + "."); | ||||||
|  |  | ||||||
|  |             byte[] pbRaw32 = CreateRawCompositeKey32(mPbMasterSeed, kdf.GetSeed(p)); | ||||||
| 			if((pbRaw32 == null) || (pbRaw32.Length != 32)) | 			if((pbRaw32 == null) || (pbRaw32.Length != 32)) | ||||||
| 				{ Debug.Assert(false); return null; } | 				{ Debug.Assert(false); return null; } | ||||||
|  |  | ||||||
| 			KdfEngine kdf = KdfPool.Get(p.KdfUuid); |  | ||||||
| 			if(kdf == null) // CryptographicExceptions are translated to "file corrupted" |  | ||||||
| 				throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph + |  | ||||||
| 					KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph + |  | ||||||
| 					"UUID: " + p.KdfUuid.ToHexString() + "."); |  | ||||||
|  |  | ||||||
| 			byte[] pbTrf32 = kdf.Transform(pbRaw32, p); | 			byte[] pbTrf32 = kdf.Transform(pbRaw32, p); | ||||||
| 			if(pbTrf32 == null) { Debug.Assert(false); return null; } | 			if(pbTrf32 == null) { Debug.Assert(false); return null; } | ||||||
| @@ -256,7 +255,7 @@ namespace KeePassLib.Keys | |||||||
|  |  | ||||||
| 	public interface ISeedBasedUserKey | 	public interface ISeedBasedUserKey | ||||||
| 	{ | 	{ | ||||||
| 		void SetParams(byte[] masterSeed); | 		void SetParams(byte[] masterSeed, byte[] mPbKdfSeed); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	public sealed class InvalidCompositeKeyException : Exception | 	public sealed class InvalidCompositeKeyException : Exception | ||||||
|   | |||||||
							
								
								
									
										84
									
								
								src/keepass2android/ChallengeXCKey.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/keepass2android/ChallengeXCKey.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | |||||||
|  | using Java.Lang; | ||||||
|  | using KeePassLib.Cryptography; | ||||||
|  | using KeePassLib.Keys; | ||||||
|  | using KeePassLib.Security; | ||||||
|  | using Exception = System.Exception; | ||||||
|  |  | ||||||
|  | namespace keepass2android | ||||||
|  | { | ||||||
|  |     class ChallengeXCKey : IUserKey, ISeedBasedUserKey | ||||||
|  |     { | ||||||
|  |         private readonly int _requestCode; | ||||||
|  |  | ||||||
|  |         public ProtectedBinary KeyData | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (Activity == null) | ||||||
|  |                     throw new Exception("Need an active Keepass2Android activity to challenge Yubikey!"); | ||||||
|  |                 Activity.RunOnUiThread( | ||||||
|  |                     () => | ||||||
|  |                     { | ||||||
|  |                         byte[] challenge = _kdfSeed; | ||||||
|  |                         byte[] challenge64 = new byte[64]; | ||||||
|  |                         for (int i = 0; i < 64; i++) | ||||||
|  |                         { | ||||||
|  |                             if (i < challenge.Length) | ||||||
|  |                             { | ||||||
|  |                                 challenge64[i] = challenge[i]; | ||||||
|  |                             } | ||||||
|  |                             else | ||||||
|  |                             { | ||||||
|  |                                 challenge64[i] = (byte)(challenge64.Length - challenge.Length); | ||||||
|  |                             } | ||||||
|  |  | ||||||
|  |                         } | ||||||
|  |                         var chalIntent = Activity.TryGetYubichallengeIntentOrPrompt(challenge64, true); | ||||||
|  |  | ||||||
|  |                         if (chalIntent == null) | ||||||
|  |                             throw new Exception("YubiChallenge not installed."); | ||||||
|  |  | ||||||
|  |                         Activity.StartActivityForResult(chalIntent, _requestCode); | ||||||
|  | 		                 | ||||||
|  | 		                 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                     }); | ||||||
|  |                 while ((Response == null) && (Error == null)) | ||||||
|  |                 { | ||||||
|  |                     Thread.Sleep(50); | ||||||
|  |                 } | ||||||
|  |                 if (Error != null) | ||||||
|  |                     throw new Exception("YubiChallenge failed: " + Error); | ||||||
|  |  | ||||||
|  |                 return new ProtectedBinary(true, CryptoUtil.HashSha256(Response)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private byte[] _kdfSeed; | ||||||
|  |  | ||||||
|  |         public ChallengeXCKey(LockingActivity activity, int requestCode) | ||||||
|  |         { | ||||||
|  |             this.Activity = activity; | ||||||
|  |             _requestCode = requestCode; | ||||||
|  |             Response = null; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void SetParams(byte[] masterSeed, byte[] mPbKdfSeed) | ||||||
|  |         { | ||||||
|  |             _kdfSeed = mPbKdfSeed; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public byte[] Response { get; set; } | ||||||
|  |  | ||||||
|  |         public string Error { get; set; } | ||||||
|  |  | ||||||
|  |         public LockingActivity Activity | ||||||
|  |         { | ||||||
|  |             get; | ||||||
|  |             set; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -16,6 +16,10 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file | |||||||
|   */ |   */ | ||||||
|  |  | ||||||
| using System; | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Android.App; | ||||||
|  | using Android.Content; | ||||||
|  | using Android.Content.PM; | ||||||
| using Android.Runtime; | using Android.Runtime; | ||||||
|  |  | ||||||
| namespace keepass2android | namespace keepass2android | ||||||
| @@ -35,7 +39,38 @@ namespace keepass2android | |||||||
| 		{ | 		{ | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		protected override void OnPause() { | 	    protected override void OnStart() | ||||||
|  | 	    { | ||||||
|  | 	        base.OnStart(); | ||||||
|  |  | ||||||
|  | 	        if (App.Kp2a.GetDb().Loaded) | ||||||
|  | 	        { | ||||||
|  | 	            var xcKey = App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey<ChallengeXCKey>(); | ||||||
|  | 	            if (xcKey != null) | ||||||
|  | 	            { | ||||||
|  | 	                xcKey.Activity = this; | ||||||
|  | 	            } | ||||||
|  |  | ||||||
|  | 	        } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|  | 	    protected override void OnStop() | ||||||
|  | 	    { | ||||||
|  | 	        base.OnStop(); | ||||||
|  | 	        if (App.Kp2a.GetDb().Loaded) | ||||||
|  | 	        { | ||||||
|  | 	            var xcKey = App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey<ChallengeXCKey>(); | ||||||
|  | 	            if (xcKey != null) | ||||||
|  | 	            { | ||||||
|  |                     //don't store a pointer to this activity in the static database object to avoid memory leak | ||||||
|  | 	                xcKey.Activity = null; | ||||||
|  | 	            } | ||||||
|  |  | ||||||
|  | 	        } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  | 	    protected override void OnPause() { | ||||||
| 			base.OnPause(); | 			base.OnPause(); | ||||||
| 			 | 			 | ||||||
| 			TimeoutHelper.Pause(this); | 			TimeoutHelper.Pause(this); | ||||||
| @@ -52,6 +87,30 @@ namespace keepass2android | |||||||
| 			 | 			 | ||||||
| 			TimeoutHelper.Resume(this); | 			TimeoutHelper.Resume(this); | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  | 	    public Intent TryGetYubichallengeIntentOrPrompt(byte[] challenge, bool promptToInstall) | ||||||
|  | 	    { | ||||||
|  | 	        Intent chalIntent = new Intent("com.yubichallenge.NFCActivity.CHALLENGE"); | ||||||
|  | 	        chalIntent.PutExtra("challenge", challenge); | ||||||
|  | 	        chalIntent.PutExtra("slot", 2); | ||||||
|  | 	        IList<ResolveInfo> activities = PackageManager.QueryIntentActivities(chalIntent, 0); | ||||||
|  | 	        bool isIntentSafe = activities.Count > 0; | ||||||
|  | 	        if (isIntentSafe) | ||||||
|  | 	        { | ||||||
|  | 	            return chalIntent; | ||||||
|  | 	        } | ||||||
|  | 	        if (promptToInstall) | ||||||
|  | 	        { | ||||||
|  | 	            AlertDialog.Builder b = new AlertDialog.Builder(this); | ||||||
|  | 	            b.SetMessage(Resource.String.YubiChallengeNotInstalled); | ||||||
|  | 	            b.SetPositiveButton(Android.Resource.String.Ok, | ||||||
|  | 	                delegate { Util.GotoUrl(this, GetString(Resource.String.MarketURL) + "com.yubichallenge"); }); | ||||||
|  | 	            b.SetNegativeButton(Resource.String.cancel, delegate { }); | ||||||
|  | 	            b.Create().Show(); | ||||||
|  | 	        } | ||||||
|  | 	        return null; | ||||||
|  | 	    } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ using System; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|  | using System.Security.Cryptography; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Xml; | using System.Xml; | ||||||
| using System.Xml.Serialization; | using System.Xml.Serialization; | ||||||
| @@ -60,7 +61,6 @@ using Process = Android.OS.Process; | |||||||
|  |  | ||||||
| using KeeChallenge; | using KeeChallenge; | ||||||
| using KeePassLib.Cryptography.KeyDerivation; | using KeePassLib.Cryptography.KeyDerivation; | ||||||
| using KeePassLib.Security; |  | ||||||
| using AlertDialog = Android.App.AlertDialog; | using AlertDialog = Android.App.AlertDialog; | ||||||
| using Enum = System.Enum; | using Enum = System.Enum; | ||||||
| using Exception = System.Exception; | using Exception = System.Exception; | ||||||
| @@ -69,72 +69,7 @@ using Toolbar = Android.Support.V7.Widget.Toolbar; | |||||||
|  |  | ||||||
| namespace keepass2android | namespace keepass2android | ||||||
| { | { | ||||||
| 	class ChallengeXCKey : IUserKey, ISeedBasedUserKey |     [Activity(Label = "@string/app_name", | ||||||
| 	{ |  | ||||||
| 		private readonly Activity _activity; |  | ||||||
| 		private readonly int _requestCode; |  | ||||||
|  |  | ||||||
| 		public ProtectedBinary KeyData |  | ||||||
| 		{ |  | ||||||
| 			get |  | ||||||
| 			{ |  | ||||||
| 				 |  | ||||||
| 				_activity.RunOnUiThread( |  | ||||||
| 					() => |  | ||||||
| 					{ |  | ||||||
| 						//TODO refactor to use code from PasswordActivity including notice to install Yubichallenge |  | ||||||
| 						Intent chalIntent = new Intent("com.yubichallenge.NFCActivity.CHALLENGE"); |  | ||||||
| 						byte[] challenge = _masterSeed; |  | ||||||
| 						byte[] challenge64 = new byte[64]; |  | ||||||
| 						for (int i = 0; i < 64; i++) |  | ||||||
| 						{ |  | ||||||
| 							if (i < challenge.Length) |  | ||||||
| 							{ |  | ||||||
| 								challenge64[i] = challenge[i]; |  | ||||||
| 							} |  | ||||||
| 							else |  | ||||||
| 							{ |  | ||||||
| 								challenge64[i] = (byte) (challenge64.Length - challenge.Length); |  | ||||||
| 							} |  | ||||||
| 							 |  | ||||||
| 						} |  | ||||||
|  |  | ||||||
| 						Kp2aLog.Log(MemUtil.ByteArrayToHexString(challenge64)); |  | ||||||
|  |  | ||||||
| 						chalIntent.PutExtra("challenge", challenge64); |  | ||||||
| 						chalIntent.PutExtra("slot", 2); |  | ||||||
| 						IList<ResolveInfo> activities = _activity.PackageManager.QueryIntentActivities(chalIntent, 0); |  | ||||||
| 						bool isIntentSafe = activities.Count > 0; |  | ||||||
| 						if (isIntentSafe) |  | ||||||
| 						{ |  | ||||||
| 							_activity.StartActivityForResult(chalIntent, _requestCode); |  | ||||||
| 						} |  | ||||||
| 						else throw new Exception("TODO implement: you need YubiChallenge"); |  | ||||||
| 					}); |  | ||||||
| 				while (Response == null) |  | ||||||
| 					Thread.Sleep(100); |  | ||||||
|  |  | ||||||
| 				return new ProtectedBinary(true, Response); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		private byte[] _masterSeed; |  | ||||||
|  |  | ||||||
| 		public ChallengeXCKey(Activity activity, int requestCode) |  | ||||||
| 		{ |  | ||||||
| 			this._activity = activity; |  | ||||||
| 			_requestCode = requestCode; |  | ||||||
| 			Response = null; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		public void SetParams(byte[] masterSeed) |  | ||||||
| 		{ |  | ||||||
| 			_masterSeed = masterSeed; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		public byte[] Response { get; set; } |  | ||||||
| 	} |  | ||||||
| 	[Activity(Label = "@string/app_name", |  | ||||||
| 		ConfigurationChanges = ConfigChanges.Orientation, | 		ConfigurationChanges = ConfigChanges.Orientation, | ||||||
| 		LaunchMode = LaunchMode.SingleInstance, | 		LaunchMode = LaunchMode.SingleInstance, | ||||||
| 		WindowSoftInputMode = SoftInput.AdjustResize, | 		WindowSoftInputMode = SoftInput.AdjustResize, | ||||||
| @@ -434,69 +369,91 @@ namespace keepass2android | |||||||
| 				 | 				 | ||||||
| 				GetAuxFileLoader().LoadAuxFile(false); | 				GetAuxFileLoader().LoadAuxFile(false); | ||||||
| 			} | 			} | ||||||
|             if (requestCode == RequestCodeChallengeYubikey && resultCode == Result.Ok)  | 		    if (requestCode == RequestCodeChallengeYubikey) | ||||||
| 			{ | 		    { | ||||||
| 				try | 		        if (resultCode == Result.Ok) | ||||||
| 				{ | 		        { | ||||||
| 					byte[] challengeResponse = data.GetByteArrayExtra("response"); |  | ||||||
| 					if (_currentlyWaitingKey != null) |  | ||||||
| 					{ | 		            try | ||||||
| 						_currentlyWaitingKey.Response = challengeResponse; | 		            { | ||||||
| 						return; | 		                byte[] challengeResponse = data.GetByteArrayExtra("response"); | ||||||
| 					} | 		                if (_currentlyWaitingKey != null) | ||||||
| 					else | 		                { | ||||||
| 					{ | 		                    if ((challengeResponse != null) && (challengeResponse.Length > 0)) | ||||||
| 						_challengeProv = new KeeChallengeProv(); | 		                    { | ||||||
| 						_challengeSecret = _challengeProv.GetSecret(_chalInfo, challengeResponse); | 		                        _currentlyWaitingKey.Response = challengeResponse; | ||||||
| 						Array.Clear(challengeResponse, 0, challengeResponse.Length);	 | 		                    } | ||||||
| 					} | 		                    else | ||||||
|                      | 		                        _currentlyWaitingKey.Error = "Did not receive a valid response."; | ||||||
| 				} |  | ||||||
| 				catch (Exception e) | 		                    return; | ||||||
| 				{ |  | ||||||
| 					Kp2aLog.Log(e.ToString()); | 		                } | ||||||
| 					Toast.MakeText(this, "Error: " + e.Message, ToastLength.Long).Show(); | 		                else | ||||||
| 					return; | 		                { | ||||||
| 				} | 		                    _challengeProv = new KeeChallengeProv(); | ||||||
| 				 | 		                    _challengeSecret = _challengeProv.GetSecret(_chalInfo, challengeResponse); | ||||||
|                 UpdateOkButtonState(); | 		                    Array.Clear(challengeResponse, 0, challengeResponse.Length); | ||||||
| 				FindViewById(Resource.Id.otpInitView).Visibility = ViewStates.Gone; | 		                } | ||||||
| 			 |  | ||||||
| 				if (_challengeSecret != null) | 		            } | ||||||
|                 { | 		            catch (Exception e) | ||||||
| 					new LoadingDialog<object, object, object>(this, true, | 		            { | ||||||
| 						//doInBackground | 		                if (_currentlyWaitingKey != null) | ||||||
| 					delegate | 		                { | ||||||
| 					{ | 		                    _currentlyWaitingKey.Error = e.Message; | ||||||
| 						//save aux file | 		                } | ||||||
| 						try | 		                Kp2aLog.Log(e.ToString()); | ||||||
| 						{ | 		                Toast.MakeText(this, "Error: " + e.Message, ToastLength.Long).Show(); | ||||||
| 							ChallengeInfo temp = _challengeProv.Encrypt(_challengeSecret); | 		                return; | ||||||
| 							if (!temp.Save(_otpAuxIoc)) | 		            } | ||||||
| 							{ |  | ||||||
| 								Toast.MakeText(this, Resource.String.ErrorUpdatingChalAuxFile, ToastLength.Long).Show(); | 		            UpdateOkButtonState(); | ||||||
| 								return false; | 		            FindViewById(Resource.Id.otpInitView).Visibility = ViewStates.Gone; | ||||||
| 							} |  | ||||||
| 							 | 		            if (_challengeSecret != null) | ||||||
| 						} | 		            { | ||||||
| 						catch (Exception e) | 		                new LoadingDialog<object, object, object>(this, true, | ||||||
| 						{ | 		                    //doInBackground | ||||||
| 							Kp2aLog.LogUnexpectedError(e); | 		                    delegate | ||||||
| 						} | 		                    { | ||||||
| 						return null; | 		                        //save aux file | ||||||
| 					} | 		                        try | ||||||
| 					, delegate | 		                        { | ||||||
| 					{ | 		                            ChallengeInfo temp = _challengeProv.Encrypt(_challengeSecret); | ||||||
| 						 | 		                            if (!temp.Save(_otpAuxIoc)) | ||||||
| 					}).Execute(); | 		                            { | ||||||
|              | 		                                Toast.MakeText(this, Resource.String.ErrorUpdatingChalAuxFile, ToastLength.Long) | ||||||
|                 } | 		                                    .Show(); | ||||||
|                 else | 		                                return false; | ||||||
|                 { | 		                            } | ||||||
|                     Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show(); |  | ||||||
|                     return; | 		                        } | ||||||
|                 } | 		                        catch (Exception e) | ||||||
| 			} | 		                        { | ||||||
|  | 		                            Kp2aLog.LogUnexpectedError(e); | ||||||
|  | 		                        } | ||||||
|  | 		                        return null; | ||||||
|  | 		                    } | ||||||
|  | 		                    , delegate | ||||||
|  | 		                    { | ||||||
|  |  | ||||||
|  | 		                    }).Execute(); | ||||||
|  |  | ||||||
|  | 		            } | ||||||
|  | 		            else | ||||||
|  | 		            { | ||||||
|  | 		                Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show(); | ||||||
|  | 		                return; | ||||||
|  | 		            } | ||||||
|  | 		        } | ||||||
|  | 		    } | ||||||
|  | 		    else | ||||||
|  | 		    { | ||||||
|  | 		        if (_currentlyWaitingKey != null) | ||||||
|  | 		            _currentlyWaitingKey.Error = "Cancelled Yubichallenge."; | ||||||
|  | 		    } | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		private AuxFileLoader GetAuxFileLoader() | 		private AuxFileLoader GetAuxFileLoader() | ||||||
| @@ -690,27 +647,12 @@ namespace keepass2android | |||||||
|  |  | ||||||
| 			protected override void HandleSuccess() | 			protected override void HandleSuccess() | ||||||
| 			{ | 			{ | ||||||
| 				Intent chalIntent = new Intent("com.yubichallenge.NFCActivity.CHALLENGE"); | 			    var chalIntent = Activity.TryGetYubichallengeIntentOrPrompt(Activity._chalInfo.Challenge, true); | ||||||
| 				chalIntent.PutExtra("challenge", Activity._chalInfo.Challenge); |  | ||||||
| 				chalIntent.PutExtra("slot", 2); |                 if (chalIntent != null) | ||||||
| 				IList<ResolveInfo> activities = Activity.PackageManager.QueryIntentActivities(chalIntent, 0); | 			    { | ||||||
| 				bool isIntentSafe = activities.Count > 0; | 			        Activity.StartActivityForResult(chalIntent, RequestCodeChallengeYubikey); | ||||||
| 				if (isIntentSafe) |                 } | ||||||
| 				{ |  | ||||||
| 					Activity.StartActivityForResult(chalIntent, RequestCodeChallengeYubikey); |  | ||||||
| 				} |  | ||||||
| 				else |  | ||||||
| 				{ |  | ||||||
| 					AlertDialog.Builder b = new AlertDialog.Builder(Activity); |  | ||||||
| 					b.SetMessage(Resource.String.YubiChallengeNotInstalled); |  | ||||||
| 					b.SetPositiveButton(Android.Resource.String.Ok, |  | ||||||
| 										delegate |  | ||||||
| 										{ |  | ||||||
| 											Util.GotoUrl(Activity, Activity.GetString(Resource.String.MarketURL) + "com.yubichallenge"); |  | ||||||
| 										}); |  | ||||||
| 					b.SetNegativeButton(Resource.String.cancel, delegate { }); |  | ||||||
| 					b.Create().Show(); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			protected override string GetErrorMessage() | 			protected override string GetErrorMessage() | ||||||
| @@ -746,7 +688,8 @@ namespace keepass2android | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		private void ShowOtpEntry(IList<string> prefilledOtps) |  | ||||||
|  | 	    private void ShowOtpEntry(IList<string> prefilledOtps) | ||||||
| 		{ | 		{ | ||||||
| 			FindViewById(Resource.Id.otpInitView).Visibility = ViewStates.Gone; | 			FindViewById(Resource.Id.otpInitView).Visibility = ViewStates.Gone; | ||||||
| 			FindViewById(Resource.Id.otpEntry).Visibility = ViewStates.Visible; | 			FindViewById(Resource.Id.otpEntry).Visibility = ViewStates.Visible; | ||||||
|   | |||||||
| @@ -864,6 +864,7 @@ Erstes öffentliches Release</string> | |||||||
|     <item>Kennwort + OTP Secret (Recovery-Modus)</item> |     <item>Kennwort + OTP Secret (Recovery-Modus)</item> | ||||||
|     <item>Passwort + Challenge-Response</item> |     <item>Passwort + Challenge-Response</item> | ||||||
|     <item>Passwort + Challenge-Response-Secret (Recovery-Modus)</item> |     <item>Passwort + Challenge-Response-Secret (Recovery-Modus)</item> | ||||||
|  |     <item>Password + Challenge-Response for KeepassXC database</item> | ||||||
|   </string-array> |   </string-array> | ||||||
|   <string-array name="AcceptAllServerCertificates_options"> |   <string-array name="AcceptAllServerCertificates_options"> | ||||||
|     <item>Fehler bei Zertifikatsvalidierung ignorieren</item> |     <item>Fehler bei Zertifikatsvalidierung ignorieren</item> | ||||||
|   | |||||||
| @@ -1069,6 +1069,7 @@ Initial public release | |||||||
| 		<item>Password + OTP secret (recovery mode)</item> | 		<item>Password + OTP secret (recovery mode)</item> | ||||||
| 		<item>Password + Challenge-Response</item> | 		<item>Password + Challenge-Response</item> | ||||||
| 		<item>Password + Challenge-Response secret (recovery mode)</item> | 		<item>Password + Challenge-Response secret (recovery mode)</item> | ||||||
|  | 	  <item>Password + Challenge-Response for KeepassXC database</item> | ||||||
| 	</string-array> | 	</string-array> | ||||||
| 	<string-array name="AcceptAllServerCertificates_options"> | 	<string-array name="AcceptAllServerCertificates_options"> | ||||||
| 		<item>Ignore certificate validation failures</item> | 		<item>Ignore certificate validation failures</item> | ||||||
|   | |||||||
| @@ -171,6 +171,7 @@ | |||||||
|     </Reference> |     </Reference> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <Compile Include="ChallengeXCKey.cs" /> | ||||||
|     <Compile Include="EntryActivityClasses\ViewImagePopupItem.cs" /> |     <Compile Include="EntryActivityClasses\ViewImagePopupItem.cs" /> | ||||||
|     <Compile Include="ImageViewActivity.cs" /> |     <Compile Include="ImageViewActivity.cs" /> | ||||||
|     <Compile Include="addons\OtpKeyProv\EncodingUtil.cs" /> |     <Compile Include="addons\OtpKeyProv\EncodingUtil.cs" /> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll