aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/ecies/params.go
blob: fd1ceedd01d7e459d0b1282bc24edb376af5f300 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package ecies

// This file contains parameters for ECIES encryption, specifying the
// symmetric encryption and HMAC parameters.

import (
    "crypto"
    "crypto/aes"
    "crypto/cipher"
    "crypto/elliptic"
    "crypto/sha256"
    "crypto/sha512"
    "fmt"
    "hash"
)

// The default curve for this package is the NIST P256 curve, which
// provides security equivalent to AES-128.
var DefaultCurve = elliptic.P256()

var (
    ErrUnsupportedECDHAlgorithm   = fmt.Errorf("ecies: unsupported ECDH algorithm")
    ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
)

type ECIESParams struct {
    Hash      func() hash.Hash // hash function
    hashAlgo  crypto.Hash
    Cipher    func([]byte) (cipher.Block, error) // symmetric cipher
    BlockSize int                                // block size of symmetric cipher
    KeyLen    int                                // length of symmetric key
}

// Standard ECIES parameters:
// * ECIES using AES128 and HMAC-SHA-256-16
// * ECIES using AES256 and HMAC-SHA-256-32
// * ECIES using AES256 and HMAC-SHA-384-48
// * ECIES using AES256 and HMAC-SHA-512-64

var (
    ECIES_AES128_SHA256 = &ECIESParams{
        Hash:      sha256.New,
        hashAlgo:  crypto.SHA256,
        Cipher:    aes.NewCipher,
        BlockSize: aes.BlockSize,
        KeyLen:    16,
    }

    ECIES_AES256_SHA256 = &ECIESParams{
        Hash:      sha256.New,
        hashAlgo:  crypto.SHA256,
        Cipher:    aes.NewCipher,
        BlockSize: aes.BlockSize,
        KeyLen:    32,
    }

    ECIES_AES256_SHA384 = &ECIESParams{
        Hash:      sha512.New384,
        hashAlgo:  crypto.SHA384,
        Cipher:    aes.NewCipher,
        BlockSize: aes.BlockSize,
        KeyLen:    32,
    }

    ECIES_AES256_SHA512 = &ECIESParams{
        Hash:      sha512.New,
        hashAlgo:  crypto.SHA512,
        Cipher:    aes.NewCipher,
        BlockSize: aes.BlockSize,
        KeyLen:    32,
    }
)

var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
    elliptic.P256(): ECIES_AES128_SHA256,
    elliptic.P384(): ECIES_AES256_SHA384,
    elliptic.P521(): ECIES_AES256_SHA512,
}

func AddParamsForCurve(curve elliptic.Curve, params *ECIESParams) {
    paramsFromCurve[curve] = params
}

// ParamsFromCurve selects parameters optimal for the selected elliptic curve.
// Only the curves P256, P384, and P512 are supported.
func ParamsFromCurve(curve elliptic.Curve) (params *ECIESParams) {
    return paramsFromCurve[curve]

    /*
        switch curve {
        case elliptic.P256():
            return ECIES_AES128_SHA256
        case elliptic.P384():
            return ECIES_AES256_SHA384
        case elliptic.P521():
            return ECIES_AES256_SHA512
        default:
            return nil
        }
    */
}

// ASN.1 encode the ECIES parameters relevant to the encryption operations.
func paramsToASNECIES(params *ECIESParams) (asnParams asnECIESParameters) {
    if nil == params {
        return
    }
    asnParams.KDF = asnNISTConcatenationKDF
    asnParams.MAC = hmacFull
    switch params.KeyLen {
    case 16:
        asnParams.Sym = aes128CTRinECIES
    case 24:
        asnParams.Sym = aes192CTRinECIES
    case 32:
        asnParams.Sym = aes256CTRinECIES
    }
    return
}

// ASN.1 encode the ECIES parameters relevant to ECDH.
func paramsToASNECDH(params *ECIESParams) (algo asnECDHAlgorithm) {
    switch params.hashAlgo {
    case crypto.SHA224:
        algo = dhSinglePass_stdDH_sha224kdf
    case crypto.SHA256:
        algo = dhSinglePass_stdDH_sha256kdf
    case crypto.SHA384:
        algo = dhSinglePass_stdDH_sha384kdf
    case crypto.SHA512:
        algo = dhSinglePass_stdDH_sha512kdf
    }
    return
}

// ASN.1 decode the ECIES parameters relevant to the encryption stage.
func asnECIEStoParams(asnParams asnECIESParameters, params *ECIESParams) {
    if !asnParams.KDF.Cmp(asnNISTConcatenationKDF) {
        params = nil
        return
    } else if !asnParams.MAC.Cmp(hmacFull) {
        params = nil
        return
    }

    switch {
    case asnParams.Sym.Cmp(aes128CTRinECIES):
        params.KeyLen = 16
        params.BlockSize = 16
        params.Cipher = aes.NewCipher
    case asnParams.Sym.Cmp(aes192CTRinECIES):
        params.KeyLen = 24
        params.BlockSize = 16
        params.Cipher = aes.NewCipher
    case asnParams.Sym.Cmp(aes256CTRinECIES):
        params.KeyLen = 32
        params.BlockSize = 16
        params.Cipher = aes.NewCipher
    default:
        params = nil
    }
}

// ASN.1 decode the ECIES parameters relevant to ECDH.
func asnECDHtoParams(asnParams asnECDHAlgorithm, params *ECIESParams) {
    if asnParams.Cmp(dhSinglePass_stdDH_sha224kdf) {
        params.hashAlgo = crypto.SHA224
        params.Hash = sha256.New224
    } else if asnParams.Cmp(dhSinglePass_stdDH_sha256kdf) {
        params.hashAlgo = crypto.SHA256
        params.Hash = sha256.New
    } else if asnParams.Cmp(dhSinglePass_stdDH_sha384kdf) {
        params.hashAlgo = crypto.SHA384
        params.Hash = sha512.New384
    } else if asnParams.Cmp(dhSinglePass_stdDH_sha512kdf) {
        params.hashAlgo = crypto.SHA512
        params.Hash = sha512.New
    } else {
        params = nil
    }
}