private static FidoRegistrationData FromStream(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            using (var binaryReader = new BinaryReader(stream))
            {
                var reservedByte = binaryReader.ReadByte();

                if (reservedByte != RegistrationReservedByte)
                {
                    throw new InvalidOperationException(String.Format(
                                                            "Incorrect value of reserved byte (expected: 0x{0:X2} but was: 0x{1:X1})",
                                                            RegistrationReservedByte, reservedByte));
                }

                try
                {
                    var publicKeyBytes  = binaryReader.ReadBytes(65);
                    var keyHandleLength = binaryReader.ReadByte();
                    var keyHandleBytes  = binaryReader.ReadBytes(keyHandleLength);

                    var nextChunkSize       = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);
                    var certificatePosition = binaryReader.BaseStream.Position;
                    var certBytes           = binaryReader.ReadBytes(nextChunkSize);
                    var certificate         = new FidoAttestationCertificate(certBytes);
                    var certSize            = certificate.Certificate.GetEncoded().Length;

                    binaryReader.BaseStream.Position = certificatePosition + certSize;
                    nextChunkSize = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);

                    var signatureBytes = binaryReader.ReadBytes(nextChunkSize);

                    var registerResponse = new FidoRegistrationData(
                        new FidoPublicKey(publicKeyBytes),
                        new FidoKeyHandle(keyHandleBytes),
                        certificate,
                        new FidoSignature(signatureBytes));

                    return(registerResponse);
                }
                catch (Exception ex)
                {
                    var message = String.Format("Error parsing registration data ({0})", ex.Message);
                    throw new InvalidOperationException(message, ex);
                }
            }
        }
        private static FidoRegistrationData FromStream(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            using (var binaryReader = new BinaryReader(stream))
            {
                var reservedByte = binaryReader.ReadByte();

                if (reservedByte != RegistrationReservedByte)
                {
                    throw new InvalidOperationException(String.Format(
                        "Incorrect value of reserved byte (expected: 0x{0:X2} but was: 0x{1:X1})",
                        RegistrationReservedByte, reservedByte));
                }

                try
                {
                    var publicKeyBytes = binaryReader.ReadBytes(65);
                    var keyHandleLength = binaryReader.ReadByte();
                    var keyHandleBytes = binaryReader.ReadBytes(keyHandleLength);

                    var nextChunkSize = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);
                    var certificatePosition = binaryReader.BaseStream.Position;
                    var certBytes = binaryReader.ReadBytes(nextChunkSize);
                    var certificate = new FidoAttestationCertificate(certBytes);
                    var certSize = certificate.Certificate.GetEncoded().Length;

                    binaryReader.BaseStream.Position = certificatePosition + certSize;
                    nextChunkSize = (int)(binaryReader.BaseStream.Length - binaryReader.BaseStream.Position);

                    var signatureBytes = binaryReader.ReadBytes(nextChunkSize);

                    var registerResponse = new FidoRegistrationData(
                        new FidoPublicKey(publicKeyBytes),
                        new FidoKeyHandle(keyHandleBytes),
                        certificate,
                        new FidoSignature(signatureBytes));

                    return registerResponse;
                }
                catch (Exception ex)
                {
                    var message = String.Format("Error parsing registration data ({0})", ex.Message);
                    throw new InvalidOperationException(message, ex);
                }
            }
        }
        private void VerifyResponseSignature(FidoAppId appId, FidoRegistrationData registrationData, FidoClientData clientData)
        {
            if (appId == null) throw new ArgumentNullException("appId");
            if (registrationData == null) throw new ArgumentNullException("registrationData");
            if (clientData == null) throw new ArgumentNullException("clientData");

            if (String.IsNullOrEmpty(clientData.RawJsonValue))
                throw new InvalidOperationException("Client data has no JSON representation");

            var signedBytes = PackBytes(
                new byte[] { 0 },
                Helpers.Sha256(appId.ToString()),
                Helpers.Sha256(clientData.RawJsonValue),
                registrationData.KeyHandle.ToByteArray(),
                registrationData.UserPublicKey.ToByteArray());

            VerifySignature(registrationData.AttestationCertificate, registrationData.Signature, signedBytes);
        }