Crypto++  5.6.4
Free C++ class library of cryptographic schemes
eccrypto.h
Go to the documentation of this file.
1 // eccrypto.h - written and placed in the public domain by Wei Dai
2 
3 //! \file eccrypto.h
4 //! \brief Classes and functions for Elliptic Curves over prime and binary fields
5 
6 #ifndef CRYPTOPP_ECCRYPTO_H
7 #define CRYPTOPP_ECCRYPTO_H
8 
9 #include "config.h"
10 #include "cryptlib.h"
11 #include "pubkey.h"
12 #include "integer.h"
13 #include "asn.h"
14 #include "hmac.h"
15 #include "sha.h"
16 #include "gfpcrypt.h"
17 #include "dh.h"
18 #include "mqv.h"
19 #include "hmqv.h"
20 #include "fhmqv.h"
21 #include "ecp.h"
22 #include "ec2n.h"
23 
24 NAMESPACE_BEGIN(CryptoPP)
25 
26 //! \brief Elliptic Curve Parameters
27 //! \tparam EC elliptic curve field
28 //! \details This class corresponds to the ASN.1 sequence of the same name
29 //! in ANSI X9.62 and SEC 1. EC is currently defined for ECP and EC2N.
30 template <class EC>
32 {
34 
35 public:
36  typedef EC EllipticCurve;
37  typedef typename EllipticCurve::Point Point;
38  typedef Point Element;
40 
41  DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {}
42  DL_GroupParameters_EC(const OID &oid)
43  : m_compress(false), m_encodeAsOID(false) {Initialize(oid);}
44  DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
45  : m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);}
47  : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);}
48 
49  void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero())
50  {
51  this->m_groupPrecomputation.SetCurve(ec);
52  this->SetSubgroupGenerator(G);
53  m_n = n;
54  m_k = k;
55  }
56  void Initialize(const OID &oid);
57 
58  // NameValuePairs
59  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
60  void AssignFrom(const NameValuePairs &source);
61 
62  // GeneratibleCryptoMaterial interface
63  //! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values
64  /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */
65  void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
66 
67  // DL_GroupParameters
68  const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
70  const Integer & GetSubgroupOrder() const {return m_n;}
71  Integer GetCofactor() const;
72  bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
73  bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation<Element> *precomp) const;
74  bool FastSubgroupCheckAvailable() const {return false;}
75  void EncodeElement(bool reversible, const Element &element, byte *encoded) const
76  {
77  if (reversible)
78  GetCurve().EncodePoint(encoded, element, m_compress);
79  else
80  element.x.Encode(encoded, GetEncodedElementSize(false));
81  }
82  virtual unsigned int GetEncodedElementSize(bool reversible) const
83  {
84  if (reversible)
85  return GetCurve().EncodedPointSize(m_compress);
86  else
87  return GetCurve().GetField().MaxElementByteLength();
88  }
89  Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
90  {
91  Point result;
92  if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true)))
93  throw DL_BadElement();
94  if (checkForGroupMembership && !ValidateElement(1, result, NULL))
95  throw DL_BadElement();
96  return result;
97  }
98  Integer ConvertElementToInteger(const Element &element) const;
99  Integer GetMaxExponent() const {return GetSubgroupOrder()-1;}
100  bool IsIdentity(const Element &element) const {return element.identity;}
101  void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
102  static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";}
103 
104  // ASN1Key
105  OID GetAlgorithmID() const;
106 
107  // used by MQV
108  Element MultiplyElements(const Element &a, const Element &b) const;
109  Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
110 
111  // non-inherited
112 
113  // enumerate OIDs for recommended parameters, use OID() to get first one
114  static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid);
115 
116  void BERDecode(BufferedTransformation &bt);
117  void DEREncode(BufferedTransformation &bt) const;
118 
119  void SetPointCompression(bool compress) {m_compress = compress;}
120  bool GetPointCompression() const {return m_compress;}
121 
122  void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;}
123  bool GetEncodeAsOID() const {return m_encodeAsOID;}
124 
125  const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();}
126 
127  bool operator==(const ThisClass &rhs) const
128  {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);}
129 
130 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
131  const Point& GetBasePoint() const {return this->GetSubgroupGenerator();}
132  const Integer& GetBasePointOrder() const {return this->GetSubgroupOrder();}
133  void LoadRecommendedParameters(const OID &oid) {Initialize(oid);}
134 #endif
135 
136 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
137  virtual ~DL_GroupParameters_EC() {}
138 #endif
139 
140 protected:
141  unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();}
142  unsigned int ExponentLength() const {return m_n.ByteCount();}
143 
144  OID m_oid; // set if parameters loaded from a recommended curve
145  Integer m_n; // order of base point
146  mutable Integer m_k; // cofactor
147  mutable bool m_compress, m_encodeAsOID; // presentation details
148 };
149 
150 //! EC public key
151 template <class EC>
152 class DL_PublicKey_EC : public DL_PublicKeyImpl<DL_GroupParameters_EC<EC> >
153 {
154 public:
155  typedef typename EC::Point Element;
156 
157  void Initialize(const DL_GroupParameters_EC<EC> &params, const Element &Q)
158  {this->AccessGroupParameters() = params; this->SetPublicElement(Q);}
159  void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q)
160  {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);}
161 
162  // X509PublicKey
163  void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
165 
166 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
167  virtual ~DL_PublicKey_EC() {}
168 #endif
169 };
170 
171 //! EC private key
172 template <class EC>
173 class DL_PrivateKey_EC : public DL_PrivateKeyImpl<DL_GroupParameters_EC<EC> >
174 {
175 public:
176  typedef typename EC::Point Element;
177 
178  void Initialize(const DL_GroupParameters_EC<EC> &params, const Integer &x)
179  {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);}
180  void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x)
181  {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);}
182  void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC<EC> &params)
183  {this->GenerateRandom(rng, params);}
184  void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n)
185  {this->GenerateRandom(rng, DL_GroupParameters_EC<EC>(ec, G, n));}
186 
187  // PKCS8PrivateKey
188  void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size);
190 
191 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
192  virtual ~DL_PrivateKey_EC() {}
193 #endif
194 };
195 
196 //! Elliptic Curve Diffie-Hellman, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECDH">ECDH</a>
197 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
198 struct ECDH
199 {
200  typedef DH_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
201 
202 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
203  virtual ~ECDH() {}
204 #endif
205 };
206 
207 /// Elliptic Curve Menezes-Qu-Vanstone, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#ECMQV">ECMQV</a>
208 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption>
209 struct ECMQV
210 {
211  typedef MQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION> Domain;
212 
213 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
214  virtual ~ECMQV() {}
215 #endif
216 };
217 
218 //! \brief Hashed Menezes-Qu-Vanstone in ECP or EC2N
219 //! \details This implementation follows Hugo Krawczyk's <a href="http://eprint.iacr.org/2005/176">HMQV: A High-Performance
220 //! Secure Diffie-Hellman Protocol</a>. Note: this implements HMQV only. HMQV-C with Key Confirmation is not provided.
221 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
222 struct ECHMQV
223 {
224  typedef HMQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION, HASH> Domain;
225 
226 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
227  virtual ~ECHMQV() {}
228 #endif
229 };
230 
232 typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECHMQV256;
233 typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECHMQV384;
234 typedef ECHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECHMQV512;
235 
236 //! \brief Fully Hashed Menezes-Qu-Vanstone in ECP or EC2N
237 //! \details This implementation follows Augustin P. Sarr and Philippe Elbaz–Vincent, and Jean–Claude Bajard's
238 //! <a href="http://eprint.iacr.org/2009/408">A Secure and Efficient Authenticated Diffie-Hellman Protocol</a>.
239 //! Note: this is FHMQV, Protocol 5, from page 11; and not FHMQV-C.
240 template <class EC, class COFACTOR_OPTION = CPP_TYPENAME DL_GroupParameters_EC<EC>::DefaultCofactorOption, class HASH = SHA256>
241 struct ECFHMQV
242 {
243  typedef FHMQV_Domain<DL_GroupParameters_EC<EC>, COFACTOR_OPTION, HASH> Domain;
244 
245 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
246  virtual ~ECFHMQV() {}
247 #endif
248 };
249 
251 typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA256 >::Domain ECFHMQV256;
252 typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA384 >::Domain ECFHMQV384;
253 typedef ECFHMQV< ECP, DL_GroupParameters_EC< ECP >::DefaultCofactorOption, SHA512 >::Domain ECFHMQV512;
254 
255 //! EC keys
256 template <class EC>
258 {
261 
262 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
263  virtual ~DL_Keys_EC() {}
264 #endif
265 };
266 
267 template <class EC, class H>
268 struct ECDSA;
269 
270 //! ECDSA keys
271 template <class EC>
273 {
276 
277 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
278  virtual ~DL_Keys_ECDSA() {}
279 #endif
280 };
281 
282 //! ECDSA algorithm
283 template <class EC>
284 class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA<typename EC::Point>
285 {
286 public:
287  CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";}
288 
289 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
290  virtual ~DL_Algorithm_ECDSA() {}
291 #endif
292 };
293 
294 //! ECNR algorithm
295 template <class EC>
296 class DL_Algorithm_ECNR : public DL_Algorithm_NR<typename EC::Point>
297 {
298 public:
299  CRYPTOPP_CONSTEXPR static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";}
300 
301 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
302  virtual ~DL_Algorithm_ECNR() {}
303 #endif
304 };
305 
306 //! <a href="http://www.weidai.com/scan-mirror/sig.html#ECDSA">ECDSA</a>
307 template <class EC, class H>
308 struct ECDSA : public DL_SS<DL_Keys_ECDSA<EC>, DL_Algorithm_ECDSA<EC>, DL_SignatureMessageEncodingMethod_DSA, H>
309 {
310 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
311  virtual ~ECDSA() {}
312 #endif
313 };
314 
315 //! ECNR
316 template <class EC, class H = SHA>
317 struct ECNR : public DL_SS<DL_Keys_EC<EC>, DL_Algorithm_ECNR<EC>, DL_SignatureMessageEncodingMethod_NR, H>
318 {
319 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
320  virtual ~ECNR() {}
321 #endif
322 };
323 
324 //! Elliptic Curve Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#ECIES">ECIES</a>
325 /*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2.
326  The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best
327  efficiency and security. */
328 template <class EC, class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = false>
329 struct ECIES
330  : public DL_ES<
331  DL_Keys_EC<EC>,
332  DL_KeyAgreementAlgorithm_DH<typename EC::Point, COFACTOR_OPTION>,
333  DL_KeyDerivationAlgorithm_P1363<typename EC::Point, DHAES_MODE, P1363_KDF2<SHA1> >,
334  DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
335  ECIES<EC> >
336 {
337  static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized
338 
339 #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
340  virtual ~ECIES() {}
341 #endif
342 
343 #if (CRYPTOPP_GCC_VERSION >= 40500) || (CRYPTOPP_LLVM_CLANG_VERSION >= 20800)
344 } __attribute__((deprecated ("ECIES will be changing in the near future due to (1) an implementation bug and (2) an interop issue")));
345 #elif (CRYPTOPP_GCC_VERSION)
346 } __attribute__((deprecated));
347 #else
348 };
349 #endif
350 
351 NAMESPACE_END
352 
353 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
354 #include "eccrypto.cpp"
355 #endif
356 
357 NAMESPACE_BEGIN(CryptoPP)
358 
359 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<ECP>;
360 CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC<EC2N>;
361 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<ECP> >;
362 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl<DL_GroupParameters_EC<EC2N> >;
363 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<ECP>;
364 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC<EC2N>;
365 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<ECP> >;
366 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl<DL_GroupParameters_EC<EC2N> >;
367 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<ECP>;
368 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC<EC2N>;
369 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<ECP::Point>;
370 CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<EC2N::Point>;
371 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<ECP>, ECDSA<ECP, SHA256> >;
372 CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_EC<EC2N>, ECDSA<EC2N, SHA256> >;
373 
374 NAMESPACE_END
375 
376 #endif
implements the SHA-384 standard
Definition: sha.h:66
Classes for Fully Hashed Menezes-Qu-Vanstone key agreement in GF(p)
implements the SHA-256 standard
Definition: sha.h:33
This file contains helper classes/functions for implementing public key algorithms.
ECDSA keys.
Definition: eccrypto.h:272
Classes for Elliptic Curves over prime fields.
Fully Hashed Menezes-Qu-Vanstone in GF(p)
Definition: fhmqv.h:24
Elliptic Curve over GF(p), where p is prime.
Definition: ecp.h:42
Fully Hashed Menezes-Qu-Vanstone in ECP or EC2N.
Definition: eccrypto.h:241
ECDSA
Definition: eccrypto.h:268
Converts a typename to an enumerated value.
Definition: cryptlib.h:120
Abstract base classes that provide a uniform interface to this library.
Hashed Menezes-Qu-Vanstone in GF(p)
Definition: hmqv.h:23
EC keys.
Definition: eccrypto.h:257
EC public key.
Definition: eccrypto.h:152
DL_FixedBasePrecomputation< Element > & AccessBasePrecomputation()
Retrieves the group precomputation.
Definition: eccrypto.h:69
Library configuration file.
Interface for random number generators.
Definition: cryptlib.h:1193
EC private key.
Definition: eccrypto.h:173
Discrete Log (DL) encryption scheme.
Definition: pubkey.h:2237
Interface for buffered transformations.
Definition: cryptlib.h:1359
bool operator==(const OID &lhs, const OID &rhs)
Compare two OIDs for equality.
void DEREncodePrivateKey(BufferedTransformation &bt) const
encode privateKey part of privateKeyInfo, without the OCTET STRING header
Definition: eccrypto.cpp:707
Classes for Hashed Menezes-Qu-Vanstone key agreement in GF(p)
Discrete Log (DL) signature scheme.
Definition: pubkey.h:2214
Classes for Elliptic Curves over binary fields.
Classes for HMAC message authentication codes.
MQV domain for performing authenticated key agreement.
Definition: mqv.h:27
Hashed Menezes-Qu-Vanstone in ECP or EC2N.
Definition: eccrypto.h:222
Classes for Diffie-Hellman key exchange.
implements the SHA-512 standard
Definition: sha.h:57
Integer GetMaxExponent() const
Retrieves the maximum exponent for the group.
Definition: eccrypto.h:99
Elliptic Curve Menezes-Qu-Vanstone, AKA ECMQV
Definition: eccrypto.h:209
Multiple precision integer with arithmetic operations.
Definition: integer.h:45
Elliptic Curve over GF(2^n)
Definition: ec2n.h:44
Elliptic Curve Integrated Encryption Scheme, AKA ECIES
Definition: eccrypto.h:329
SHA-1
Definition: sha.h:22
ECNR algorithm.
Definition: eccrypto.h:296
Implementation of schemes based on DL over GF(p)
void DEREncodePublicKey(BufferedTransformation &bt) const
encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header ...
Definition: eccrypto.cpp:660
ECDSA algorithm.
Definition: eccrypto.h:284
Exception thrown when an invalid group element is encountered.
Definition: pubkey.h:748
Diffie-Hellman domain.
Definition: dh.h:23
Elliptic Curve Diffie-Hellman, AKA ECDH
Definition: eccrypto.h:198
Classes and functions for working with ANS.1 objects.
Classes for SHA-1 and SHA-2 family of message digests.
Elliptic Curve Parameters.
Definition: eccrypto.h:31
const DL_FixedBasePrecomputation< Element > & GetBasePrecomputation() const
Retrieves the group precomputation.
Definition: eccrypto.h:68
GDSA algorithm.
Definition: gfpcrypt.h:185
virtual unsigned int GetEncodedElementSize(bool reversible) const
Retrieves the encoded element's size.
Definition: eccrypto.h:82
Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const
Decodes the element.
Definition: eccrypto.h:89
NR algorithm.
Definition: gfpcrypt.h:221
Multiple precision integer with arithmetic operations.
static const Integer & Zero()
Integer representing 0.
Definition: integer.cpp:3014
Crypto++ library namespace.
Base implmentation of Discrete Log (DL) group parameters.
Definition: pubkey.h:971
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params)
Definition: pubkey.h:1175
Classes for Menezes–Qu–Vanstone (MQV) key agreement.
Object Identifier.
Definition: asn.h:158
const Integer & GetSubgroupOrder() const
Retrieves the subgroup order.
Definition: eccrypto.h:70
void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header ...
Definition: eccrypto.cpp:649
void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size)
decode privateKey part of privateKeyInfo, without the OCTET STRING header
Definition: eccrypto.cpp:668
ECNR.
Definition: eccrypto.h:317
Interface for retrieving values given their names.
Definition: cryptlib.h:282