/// <summary>
        /// Sign given hashes. Returns uni-signatures.
        /// </summary>
        public IEnumerable <IKsiSignature> Sign()
        {
            _canAddItems = false;

            if (_leafNodes.Count == 0)
            {
                return(new List <IKsiSignature>());
            }

            TreeNode root = _treeBuilder.GetTreeRoot();

            if (root.Left == null && root.Right == null)
            {
                Logger.Debug("Only one node in the tree. Signing the hash. Level: {0}; Hash: {1}", root.Level, root.Hash);
                return(new List <IKsiSignature>()
                {
                    _ksiService.Sign(root.Hash, root.Level)
                });
            }

            Logger.Debug("Signing root node hash. Level: {0}; Hash: {1}", root.Level, root.Hash);
            SignRequestResponsePayload signResponsePayload = _ksiService.GetSignResponsePayload(_ksiService.BeginSign(root.Hash, root.Level, null, null));

            return(CreateUniSignatures(new KsiSignature(false, false, signResponsePayload.GetSignatureChildTags())));
        }
        /// <summary>
        ///     End create signature (async).
        /// </summary>
        /// <param name="asyncResult">async result</param>
        /// <returns>KSI signature</returns>
        public IKsiSignature EndSign(IAsyncResult asyncResult)
        {
            KsiServiceAsyncResult      serviceAsyncResult = GetKsiServiceAsyncResult(asyncResult);
            SignRequestResponsePayload responsePayload    = GetSignResponsePayload(serviceAsyncResult);

            LegacyAggregationResponsePayload legacyPayload = responsePayload as LegacyAggregationResponsePayload;
            AggregationResponsePayload       payload       = responsePayload as AggregationResponsePayload;

            IKsiSignature signature = legacyPayload != null
                ? _ksiSignatureFactory.Create(legacyPayload, serviceAsyncResult.DocumentHash, serviceAsyncResult.Level)
                : _ksiSignatureFactory.Create(payload, serviceAsyncResult.DocumentHash, serviceAsyncResult.Level);

            Logger.Debug("End sign successful (request id: {0}){1}{2}", serviceAsyncResult.RequestId, Environment.NewLine, signature);

            return(signature);
        }
        private SignRequestResponsePayload GetSignResponsePayload(KsiServiceAsyncResult serviceAsyncResult)
        {
            if (_signingServiceProtocol == null)
            {
                throw new KsiServiceException("Signing service protocol is missing from service.");
            }

            if (!serviceAsyncResult.IsCompleted)
            {
                serviceAsyncResult.AsyncWaitHandle.WaitOne();
            }

            byte[]     data    = _signingServiceProtocol.EndSign(serviceAsyncResult);
            PduPayload payload = SignRequestResponseParser.Parse(data, serviceAsyncResult.RequestId);
            SignRequestResponsePayload signResponsePayload = payload as SignRequestResponsePayload;

            if (signResponsePayload == null)
            {
                Logger.Warn("Sign request failed. Invalid response payload.{0}Payload:{0}{1}", Environment.NewLine, payload);
                throw new KsiServiceException("Invalid sign response payload. Type: " + payload.Type);
            }

            return(signResponsePayload);
        }