Beispiel #1
0
        /// <summary>
        /// Verifies contents of list of relationships returned by the profile server against the expected list of cards.
        /// </summary>
        /// <param name="CardNumbers">Numbers of cards that are expected to be in the relationship list.</param>
        /// <param name="RelationshipList">Card list returned by the profile server.</param>
        /// <returns>true if the <paramref name="RelationshipList"/> contains cards specified by card numbers in <paramref name="CardNumbers"/>.</returns>
        public bool CheckRelationships(HashSet <int> CardNumbers, IEnumerable <IdentityRelationship> RelationshipList)
        {
            log.Trace("()");
            bool error = false;

            bool[] cardsOk = new bool[SignedCards.Count];
            foreach (IdentityRelationship relationship in RelationshipList)
            {
                CardApplicationInformation cardApplication = relationship.CardApplication;
                byte[] cardApplicationSignature            = relationship.CardApplicationSignature.ToByteArray();
                SignedRelationshipCard signedCard          = relationship.Card;
                RelationshipCard       card = signedCard.Card;
                byte[] cardId = card.CardId.ToByteArray();

                int cardIndex = -1;
                for (int i = 0; i < SignedCards.Count; i++)
                {
                    byte[] existingCardId = SignedCards[i].Card.CardId.ToByteArray();
                    if (!cardsOk[i] && (StructuralComparisons.StructuralComparer.Compare(existingCardId, cardId) == 0))
                    {
                        cardIndex = i;
                        break;
                    }
                }

                if (cardIndex != -1)
                {
                    if (CardNumbers.Contains(cardIndex + 1))
                    {
                        byte[] issuerPublicKey = card.IssuerPublicKey.ToByteArray();
                        byte[] cardSignature   = signedCard.IssuerSignature.ToByteArray();

                        bool cardSignatureOk = Ed25519.Verify(cardSignature, cardId, issuerPublicKey);
                        bool cardContentOk   = StructuralComparisons.StructuralComparer.Compare(SignedCards[cardIndex].ToByteArray(), signedCard.ToByteArray()) == 0;

                        bool cardOk = cardSignatureOk && cardContentOk;

                        byte[] recipientPublicKey     = card.RecipientPublicKey.ToByteArray();
                        bool   applicationSignatureOk = Ed25519.Verify(cardApplicationSignature, cardApplication.ToByteArray(), recipientPublicKey);
                        bool   applicationContentOk   = StructuralComparisons.StructuralComparer.Compare(CardApplications[cardIndex].ToByteArray(), cardApplication.ToByteArray()) == 0;
                        bool   applicationOk          = applicationSignatureOk && applicationContentOk;

                        if (!cardOk)
                        {
                            log.Trace("Card index {0} is corrupted.", cardIndex + 1);
                            error = true;
                            break;
                        }

                        if (!applicationOk)
                        {
                            log.Trace("Card application ID '{0}' for card index {1} is corrupted.", Crypto.ToHex(cardApplication.ApplicationId.ToByteArray()), cardIndex + 1);
                            error = true;
                            break;
                        }

                        cardsOk[cardIndex] = true;
                    }
                }
                else
                {
                    log.Trace("Card ID '{0}' not recognized.", Crypto.ToHex(cardId));
                    error = true;
                    break;
                }
            }

            foreach (int index in CardNumbers)
            {
                if (!cardsOk[index - 1])
                {
                    log.Trace("Card index {0} not retrieved.", index);
                    error = true;
                    break;
                }
            }

            bool res = !error;

            log.Trace("(-):{0}", res);
            return(res);
        }
Beispiel #2
0
        /// <summary>
        /// Checks whether AddRelatedIdentityRequest request is valid.
        /// </summary>
        /// <param name="Client">Client that sent the request.</param>
        /// <param name="AddRelatedIdentityRequest">Client's request message to validate.</param>
        /// <param name="MessageBuilder">Client's network message builder.</param>
        /// <param name="RequestMessage">Full request message from client.</param>
        /// <param name="ErrorResponse">If the function fails, this is filled with error response message that is ready to be sent to the client.</param>
        /// <returns>true if the profile update request can be applied, false otherwise.</returns>
        public static bool ValidateAddRelatedIdentityRequest(IncomingClient Client, AddRelatedIdentityRequest AddRelatedIdentityRequest, PsMessageBuilder MessageBuilder, PsProtocolMessage RequestMessage, out PsProtocolMessage ErrorResponse)
        {
            log.Trace("()");

            bool res = false;

            ErrorResponse = null;
            string details = null;

            if (AddRelatedIdentityRequest == null)
            {
                AddRelatedIdentityRequest = new AddRelatedIdentityRequest();
            }
            if (AddRelatedIdentityRequest.CardApplication == null)
            {
                AddRelatedIdentityRequest.CardApplication = new CardApplicationInformation();
            }
            if (AddRelatedIdentityRequest.SignedCard == null)
            {
                AddRelatedIdentityRequest.SignedCard = new SignedRelationshipCard();
            }
            if (AddRelatedIdentityRequest.SignedCard.Card == null)
            {
                AddRelatedIdentityRequest.SignedCard.Card = new RelationshipCard();
            }

            CardApplicationInformation cardApplication = AddRelatedIdentityRequest.CardApplication;
            SignedRelationshipCard     signedCard      = AddRelatedIdentityRequest.SignedCard;
            RelationshipCard           card            = signedCard.Card;

            byte[] applicationId = cardApplication.ApplicationId.ToByteArray();
            byte[] cardId        = card.CardId.ToByteArray();

            if ((applicationId.Length == 0) || (applicationId.Length > RelatedIdentity.CardIdentifierLength))
            {
                log.Debug("Card application ID is invalid.");
                details = "cardApplication.applicationId";
            }

            if (details == null)
            {
                byte[] appCardId = cardApplication.CardId.ToByteArray();
                if (!ByteArrayComparer.Equals(cardId, appCardId))
                {
                    log.Debug("Card IDs in application card and relationship card do not match.");
                    details = "cardApplication.cardId";
                }
            }

            if (details == null)
            {
                if (card.ValidFrom > card.ValidTo)
                {
                    log.Debug("Card validFrom field is greater than validTo field.");
                    details = "signedCard.card.validFrom";
                }
                else
                {
                    DateTime?cardValidFrom = ProtocolHelper.UnixTimestampMsToDateTime(card.ValidFrom);
                    DateTime?cardValidTo   = ProtocolHelper.UnixTimestampMsToDateTime(card.ValidTo);
                    if (cardValidFrom == null)
                    {
                        log.Debug("Card validFrom value '{0}' is not a valid timestamp.", card.ValidFrom);
                        details = "signedCard.card.validFrom";
                    }
                    else if (cardValidTo == null)
                    {
                        log.Debug("Card validTo value '{0}' is not a valid timestamp.", card.ValidTo);
                        details = "signedCard.card.validTo";
                    }
                }
            }

            if (details == null)
            {
                byte[] issuerPublicKey = card.IssuerPublicKey.ToByteArray();
                bool   pubKeyValid     = (0 < issuerPublicKey.Length) && (issuerPublicKey.Length <= ProtocolHelper.MaxPublicKeyLengthBytes);
                if (!pubKeyValid)
                {
                    log.Debug("Issuer public key has invalid length {0} bytes.", issuerPublicKey.Length);
                    details = "signedCard.card.issuerPublicKey";
                }
            }

            if (details == null)
            {
                byte[] recipientPublicKey = card.RecipientPublicKey.ToByteArray();
                if (!ByteArrayComparer.Equals(recipientPublicKey, Client.PublicKey))
                {
                    log.Debug("Caller is not recipient of the card.");
                    details = "signedCard.card.recipientPublicKey";
                }
            }

            if (details == null)
            {
                if (!Client.MessageBuilder.VerifySignedConversationRequestBodyPart(RequestMessage, cardApplication.ToByteArray(), Client.PublicKey))
                {
                    log.Debug("Caller is not recipient of the card.");
                    ErrorResponse = Client.MessageBuilder.CreateErrorInvalidSignatureResponse(RequestMessage);
                    details       = "";
                }
            }

            if (details == null)
            {
                SemVer cardVersion = new SemVer(card.Version);
                if (!cardVersion.Equals(SemVer.V100))
                {
                    log.Debug("Card version is invalid or not supported.");
                    details = "signedCard.card.version";
                }
            }

            if (details == null)
            {
                if (Encoding.UTF8.GetByteCount(card.Type) > PsMessageBuilder.MaxRelationshipCardTypeLengthBytes)
                {
                    log.Debug("Card type is too long.");
                    details = "signedCard.card.type";
                }
            }

            if (details == null)
            {
                RelationshipCard emptyIdCard = new RelationshipCard()
                {
                    CardId             = ProtocolHelper.ByteArrayToByteString(new byte[RelatedIdentity.CardIdentifierLength]),
                    Version            = card.Version,
                    IssuerPublicKey    = card.IssuerPublicKey,
                    RecipientPublicKey = card.RecipientPublicKey,
                    Type      = card.Type,
                    ValidFrom = card.ValidFrom,
                    ValidTo   = card.ValidTo
                };

                byte[] hash = Crypto.Sha256(emptyIdCard.ToByteArray());
                if (!ByteArrayComparer.Equals(hash, cardId))
                {
                    log.Debug("Card ID '{0}' does not match its hash '{1}'.", cardId.ToHex(64), hash.ToHex());
                    details = "signedCard.card.cardId";
                }
            }

            if (details == null)
            {
                byte[] issuerSignature = signedCard.IssuerSignature.ToByteArray();
                byte[] issuerPublicKey = card.IssuerPublicKey.ToByteArray();
                if (!Ed25519.Verify(issuerSignature, cardId, issuerPublicKey))
                {
                    log.Debug("Issuer signature is invalid.");
                    details = "signedCard.issuerSignature";
                }
            }

            if (details == null)
            {
                res = true;
            }
            else
            {
                if (ErrorResponse == null)
                {
                    ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, details);
                }
            }

            log.Trace("(-):{0}", res);
            return(res);
        }