File: Psha1DerivedKeyGenerator.cs

package info (click to toggle)
mono 4.6.2.7%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 778,148 kB
  • ctags: 914,052
  • sloc: cs: 5,779,509; xml: 2,773,713; ansic: 432,645; sh: 14,749; makefile: 12,361; perl: 2,488; python: 1,434; cpp: 849; asm: 531; sql: 95; sed: 16; php: 1
file content (114 lines) | stat: -rw-r--r-- 4,225 bytes parent folder | download | duplicates (7)
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------

namespace System.IdentityModel
{
    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    using System.ServiceModel.Diagnostics;

    sealed class Psha1DerivedKeyGenerator
    {
        byte[] key;

        public Psha1DerivedKeyGenerator(byte[] key)
        {
            if (key == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key");
            }
            this.key = key;
        }

        public byte[] GenerateDerivedKey(byte[] label, byte[] nonce, int derivedKeySize, int position)
        {
            if (label == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("label");
            }
            if (nonce == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("nonce");
            }
            ManagedPsha1 dkcp = new ManagedPsha1(key, label, nonce);
            return dkcp.GetDerivedKey(derivedKeySize, position);
        }

        // private class to do the real work
        // Note: Though named ManagedPsha1, this works for both fips and non-fips compliance
        sealed class ManagedPsha1
        {
            byte[] aValue;
            byte[] buffer;
            byte[] chunk;
            KeyedHashAlgorithm hmac;
            int index;
            int position;
            byte[] secret;
            byte[] seed;

            // assume arguments are already validated
            public ManagedPsha1(byte[] secret, byte[] label, byte[] seed)
            {
                this.secret = secret;
                this.seed = DiagnosticUtility.Utility.AllocateByteArray(checked(label.Length + seed.Length));
                label.CopyTo(this.seed, 0);
                seed.CopyTo(this.seed, label.Length);

                this.aValue = this.seed;
                this.chunk = new byte[0];
                this.index = 0;
                this.position = 0;
                this.hmac = CryptoHelper.NewHmacSha1KeyedHashAlgorithm(secret);

                this.buffer = DiagnosticUtility.Utility.AllocateByteArray(checked(this.hmac.HashSize / 8 + this.seed.Length));
            }

            public byte[] GetDerivedKey(int derivedKeySize, int position)
            {
                if (derivedKeySize < 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("derivedKeySize", SR.GetString(SR.ValueMustBeNonNegative)));
                }
                if (this.position > position)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("position", SR.GetString(SR.ValueMustBeInRange, 0, this.position)));
                }

                // Seek to the desired position in the pseudo-random stream.
                while (this.position < position)
                {
                    GetByte();
                }
                int sizeInBytes = derivedKeySize / 8;
                byte[] derivedKey = new byte[sizeInBytes];
                for (int i = 0; i < sizeInBytes; i++)
                {
                    derivedKey[i] = GetByte();
                }
                return derivedKey;
            }

            byte GetByte()
            {
                if (index >= chunk.Length)
                {
                    // Calculate A(i) = HMAC_SHA1(secret, A(i-1)).
                    hmac.Initialize();
                    this.aValue = hmac.ComputeHash(this.aValue);
                    // Calculate P_SHA1(secret, seed)[j] = HMAC_SHA1(secret, A(j+1) || seed).
                    this.aValue.CopyTo(buffer, 0);
                    this.seed.CopyTo(buffer, this.aValue.Length);
                    hmac.Initialize();
                    this.chunk = hmac.ComputeHash(buffer);
                    index = 0;
                }
                position++;
                return chunk[index++];
            }
        }
    }
}