using Java.Lang; using keepass2android; using KeePassLib.Cryptography; using KeePassLib.Keys; using KeePassLib.Security; using KeePassLib.Serialization; using Exception = System.Exception; namespace keepass2android { public 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) { Error = Activity.GetString(Resource.String.NoChallengeApp); } else { Activity.StartActivityForResult(chalIntent, _requestCode); } }); while ((Response == null) && (Error == null)) { System.Threading.Thread.Sleep(50); } if (Error != null) { var error = Error; Error = null; throw new Exception("YubiChallenge failed: " + error); } var result = CryptoUtil.HashSha256(Response); Response = null; return new ProtectedBinary(true, result); } } public uint GetMinKdbxVersion() { return KdbxFile.FileVersion32_4; } 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; } } }