summary refs log tree commit diff
path: root/crypto/src/asn1/tsp/PartialHashtree.cs
blob: a32a9f18b105a93e84efd947734c5942d799e228 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;

using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;

namespace Org.BouncyCastle.Asn1.Tsp
{
    /**
     * Implementation of PartialHashtree, as defined in RFC 4998.
     * <p>
     * The ASN.1 notation for a PartialHashTree is:
     * <p>
     * PartialHashtree ::= SEQUENCE OF OCTET STRING
     */
    public class PartialHashtree
        : Asn1Encodable
    {
        /**
         * Return a PartialHashtree from the given object.
         *
         * @param obj the object we want converted.
         * @return a PartialHashtree instance, or null.
         * @throws IllegalArgumentException if the object cannot be converted.
         */
        public static PartialHashtree GetInstance(object obj)
        {
            if (obj == null)
                return null;
            if (obj is PartialHashtree partialHashtree)
                return partialHashtree;
            return new PartialHashtree(Asn1Sequence.GetInstance(obj));
        }

        public static PartialHashtree GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
        {
            return new PartialHashtree(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
        }

        /**
         * Hash values that constitute the hash tree, as ASN.1 Octet Strings.
         */
        private readonly Asn1Sequence m_values;

        private PartialHashtree(Asn1Sequence values)
        {
            for (int i = 0; i != values.Count; i++)
            {
                if (!(values[i] is Asn1OctetString))
                    throw new ArgumentException("unknown object in constructor: " + Platform.GetTypeName(values[i]));
            }
            m_values = values;
        }

        public PartialHashtree(byte[] value)
        {
            m_values = new DerSequence(new DerOctetString(Arrays.Clone(value)));
        }

        public PartialHashtree(byte[][] values)
        {
            Asn1EncodableVector v = new Asn1EncodableVector(values.Length);

            for (int i = 0; i != values.Length; i++)
            {
                v.Add(new DerOctetString(Arrays.Clone(values[i])));
            }

            m_values = new DerSequence(v);
        }

        public virtual int ValueCount => m_values.Count;

        public virtual byte[][] GetValues() => m_values.MapElements(
            element => Arrays.Clone(Asn1OctetString.GetInstance(element).GetOctets()));

        public virtual bool ContainsHash(byte[] hash)
        {
            foreach (Asn1OctetString octetString in m_values)
            {
                byte[] currentHash = octetString.GetOctets();

                if (Arrays.FixedTimeEquals(hash, currentHash))
                    return true;
            }

            return false;
        }

        public override Asn1Object ToAsn1Object() => m_values;
    }
}