--- rsaref/doc/rsaref.txt 2018/04/24 16:37:52 1.1.1.1 +++ rsaref/doc/rsaref.txt 2018/04/24 16:38:26 1.1.1.2 @@ -1,32 +1,90 @@ - RSAREF(TM): - A Cryptographic Toolkit for Privacy-Enhanced Mail + RSAREF(TM): A Cryptographic Toolkit Library Reference Manual RSA Laboratories - March 2, 1992 + March 21, 1994 - Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data + Version 2.0 + + Copyright (C) 1991-4 RSA Laboratories, a division of RSA Data Security, Inc. All rights reserved. -INTRODUCTION +1. INTRODUCTION + +This manual is a reference guide for users of RSAREF, RSA +Laboratories' portable, educational, reference implementation of +cryptography. + +RSAREF supports the following algorithms: + + o RSA encryption and key generation [1], as defined by RSA + Laboratories' Public-Key Cryptography Standards (PKCS) [2] + + o MD2 and MD5 message digests [3,4] + + o DES (Data Encryption Standard) in cipher-block chaining mode + [5,6] -This manual is a reference guide for users of RSAREF, a cryptographic -toolkit designed to facilitate rapid development of Internet -Privacy-Enhanced Mail (PEM) [1-3] implementations. - -RSAREF supports the following PEM-specified algorithms: - - - RSA encryption and key generation, as defined by RSA Data - Security's Public-Key Cryptography Standards (PKCS) [4] - - MD2 and MD5 message digests [3,5,6] - - DES (Data Encryption Standard) in cipher-block chaining mode - [7,8] + o Diffie-Hellman key agreement [7], as defined by PKCS #3 [8] + + o DESX, RSA Data Security's efficient, secure DES enhancement + + o Triple-DES, for added security with three DES operations RSAREF is written entirely in C. Its application interface includes the following routines: + R_SignInit, computes a digital signature on data of + R_SignUpdate, arbitrary length, processing in parts + and R_SignFinal + + R_VerifyInit, verifies a digital signature, processing in + R_VerifyUpdate, parts + and R_VerifyFinal + + R_SealInit, creates a digital envelope on data of + R_SealUpdate, arbitrary length, processing in parts + and R_SealFinal + + R_OpenInit, opens a digital envelope, processing in + R_OpenUpdate, parts + and R_OpenFinal + + R_DigestInit, digests data of arbitrary length, processing + R_DigestUpdate, in parts + and R_DigestFinal + + R_EncodePEMBlock encodes a message in printable ASCII + according to RFC 1421 [9] + R_DecodePEMBlock decodes a message encoded according to RFC + 1421 + + R_GeneratePEMKeys generates an RSA public/private key pair + + R_RandomInit initializes a random structure + R_RandomUpdate mixes bytes into a random structure +R_GetRandomBytesNeeded computes the number of mix-in bytes still + needed to seed a random structure + R_RandomFinal zeroizes a random structure + + R_GenerateDHParams generates Diffie-Hellman parameters + R_SetupDHAgreement sets up a key agreement + R_ComputeDHAgreedKey computes the agreed-upon key + +An Internet Privacy-Enhanced Mail [9-12] implementation can be built +directly on top of these routines, together with message parsing and +formatting routines and certificate-management routines. +Implementations of PKCS #7 and #10 [13,14] can be built in a similar +manner. Other secure applications can be built on top of the +Diffie-Hellman routines. + +The following routines are supported for backward compatibility with +RSAREF 1.0: + R_SignPEMBlock computes a digital signature on a message + R_SignBlock computes a digital signature on a block of + data such as a certificate R_VerifyPEMSignature verifies a digital signature on a message R_VerifyBlockSignature verifies a digital signature on a block of data such as a certificate @@ -36,37 +94,22 @@ R_VerifyBlockSignature verifies a digi R_OpenPEMBlock decrypts an encrypted message and verifies a digital signature - R_DigestBlock computes a message digest on a message + R_DigestBlock computes the message digest of a message - R_GeneratePEMKeys generates an RSA public/private key pair +This manual is divided into eight sections and three appendices. - R_RandomInit initializes a random structure - R_RandomUpdate mixes bytes into a random structure -R_GetRandomBytesNeeded computes the number of mix-in bytes still - needed to seed a random structure - R_RandomFinal zeroizes a random structure - -A simple PEM implementation can be built directly on top of these -routines, together with message parsing and formatting routines and -certificate-management routines. - -This manual is divided into five main parts and three appendices. - -This part introduces RSAREF. The next three parts explain RSAREF -procedures: random structures; cryptographic enhancements; and -key-pair generation. The last part documents the platform-specific -run-time library. +This section introduces RSAREF. The next six sections explain RSAREF +procedures: random structures; cryptographic enhancements; printable +ASCII encoding and decoding; key-pair generation; Diffie-Hellman key +agreement; and version 1.0 routines. The last section documents the +platform-specific run-time library. Appendix A lists RSAREF error types. Appendix B lists RSAREF types and constants. Appendix C lists platform-specific types and constants. -RSAREF is intended to be compatible with forthcoming revised versions -of the PEM RFCs, which are now in the unofficial "Internet-Draft" -stage. - -RANDOM STRUCTURES +2. RANDOM STRUCTURES A random structure contains a seed from which a pseudorandom sequence of bytes is derived. RSAREF generates keys and pads RSA encryption @@ -75,8 +118,8 @@ blocks with bytes derived from a random Random structures are used by both message-processing and key-generation applications. -RSAREF initializes a random structure with the procedure -R_RandomInit. A typical application calls R_RandomInit on entry. +RSAREF sets up a random structure with the procedure R_RandomInit. A +typical application calls R_RandomInit on entry. A new random structure is not ready for use until it is seeded by mixing in some random bytes. RSAREF seeds a random structure with the @@ -96,11 +139,10 @@ int R_RandomInit ( R_RANDOM_STRUCT *randomStruct /* new random structure */ ); -R_RandomInit initializes a new random structure, storing the result -in randomStruct. +R_RandomInit sets up a new random structure. -Return value: 0 success - nonzero reserved for future compatibility +Return value: 0 success + nonzero reserved for future compatibility R_RandomUpdate @@ -113,8 +155,8 @@ int R_RandomUpdate ( R_RandomUpdate mixes blockLen bytes from block into randomStruct. -Return value: 0 success - nonzero reserved for future compatibility +Return value: 0 success + nonzero reserved for future compatibility R_GetRandomBytesNeeded @@ -127,8 +169,8 @@ int R_GetRandomBytesNeeded ( R_GetRandomBytesNeeded computes the number of mix-in bytes still needed to seed randomStruct, storing the result in bytesNeeded. -Return value: 0 success - nonzero reserved for future compatibility +Return value: 0 success + nonzero reserved for future compatibility R_RandomFinal @@ -142,33 +184,715 @@ R_RandomFinal zeroizes randomStruct. No return value. -CRYPTOGRAPHIC ENHANCEMENTS +3. CRYPTOGRAPHIC ENHANCEMENTS + +RSAREF's cryptographic enhancements fall into five groups: signing +data; verifying signatures; sealing data in digital envelopes; +opening digital envelopes; and digesting data. + +All the procedures process data in parts; it is not necessary for all +data to be stored in memory at once. + + +3.1 Signing data + +RSAREF signs data with three procedures: R_SignInit, R_SignUpdate, +and R_SignFinal. These procedures are typically called by +message-processing applications, by key-generation applications when +constructing a PEM or PKCS certification request, and by +certification applications when signing a certificate. + +An application first calls R_SignInit, giving an integer specifying +which message-digest algorithm to apply (see Appendix D). R_SignInit +sets up a context for the signature operation, and returns the +context. + +The application then calls R_SignUpdate any number of times, giving +the context and the next data part. R_SignUpdate digests the part. + +After all the parts are supplied, the application calls R_SignFinal, +giving the context and the signer's RSA private key. R_SignFinal +encrypts the message digest with the private key and returns the +result, which is the signature. + +An application may call R_SignUpdate again after R_SignFinal to +sign other data, without setting up a new context. + + +R_SignInit + +int R_SignInit ( + R_SIGNATURE_CTX *context, /* new context */ + int digestAlgorithm /* message-digest algorithm */ +); + +R_SignInit begins a signature operation, setting up a new context. + +digestAlgorithm is the algorithm with which data are digested, and +must be one of the values listed in Appendix D. + +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + + +R_SignUpdate + +int R_SignUpdate ( + R_SIGNATURE_CTX *context, /* context */ + unsigned char *partIn, /* next data part */ + unsigned char partInLen /* length of next data part */ +); + +R_SignUpdate continues a signature operation, digesting partIn, the +next data part, with the specified message-digest algorithm. It may +be called any number of times. + +Return value: 0 success + + +R_SignFinal + +int R_SignFinal ( + R_SIGNATURE_CTX *context, /* context */ + unsigned char *signature, /* signature */ + unsigned int *signatureLen, /* length of signature */ + R_RSA_PRIVATE_KEY *privateKey /* signer's RSA private key */ +); + +R_SignFinal completes a signature operation, encrypting the message +digest with the signer's private key. It stores the resulting +signature in signature and its length in signatureLen. + +signatureLen will not be greater than MAX_SIGNATURE_LEN. + +Return value: 0 success + RE_PRIVATE_KEY privateKey cannot encrypt message digest + + +3.2 Verifying a signature + +RSAREF verifies signatures with three procedures: R_VerifyInit, +R_VerifyUpdate, and R_VerifyFinal. These procedures are typically +called by message-processing applications and by certification +applications when processing a certification request. + +An application first calls R_VerifyInit, giving an integer specifying +which message-digest algorithm to apply (see Appendix D). +R_VerifyInit sets up a context for the verification operation, and +returns the context. + +The application then calls R_VerifyUpdate any number of times, giving +the context and the next data part. R_VerifyUpdate digests the part. + +After all the parts are supplied, the application calls +R_VerifyFinal, giving the context, the signer's RSA public key, and +the signature. R_SignFinal decrypts the signature with the public key +and compares the result to the message digest to see whether the +signature is valid. + +An application may call R_VerifyUpdate again after R_VerifyFinal to +verify other signatures, without setting up a new context. + + +R_VerifyInit + +int R_VerifyInit ( + R_SIGNATURE_CTX *context, /* new context */ + int digestAlgorithm /* message-digest algorithm */ +); + +R_VerifyInit begins a verification operation, setting up a new +context. + +digestAlgorithm is the algorithm with which data are digested, and +must be one of the values listed in Appendix D. + +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + + +R_VerifyUpdate + +int R_VerifyUpdate ( + R_SIGNATURE_CTX *context, /* context */ + unsigned char *partIn, /* next data part */ + unsigned int partInLen /* length of next data part */ +); + +R_VerifyUpdate continues a verification operation, digesting partIn, +the next data part, with the specified message-digest algorithm. It +may be called any number of times. + +Return value: 0 success + + +R_VerifyFinal + +int R_VerifyFinal ( + R_SIGNATURE_CTX *context, /* context */ + unsigned char *signature, /* signature */ + unsigned int signatureLen, /* length of signature */ + R_RSA_PUBLIC_KEY *publicKey /* signer's RSA public key */ +); + +R_VerifyFinal completes a verification operation, decrypting the +signature with the signer's public key and comparing it to the +message digest. + +signatureLen must not be greater than MAX_SIGNATURE_LEN. + +Return value: 0 success + RE_LEN signatureLen out of range + RE_PUBLIC_KEY publicKey cannot decrypt signature + RE_SIGNATURE signature is incorrect + + +3.3 Sealing data in a digital envelope + +RSAREF seals data in digital envelopes with three procedures: +R_SealInit, R_SealUpdate, and R_SealFinal. There may be any number of +recipients. These procedures are typically called by +message-processing applications. + +An application first calls R_SealInit, giving an integer specifying +which data encryption algorithm to apply (see Appendix D), the public +key of each recipient, and a random structure. R_SealInit sets up a +context for the sealing operation, generates a data encryption key +and an initialization vector, and encrypts the data encryption key +with each recipient's public key. It returns the context, the +initialization vector, and the encrypted data encryption keys. + +The application then calls R_SealUpdate any number of times, giving +the context and the next data part. R_SealUpdate encrypts the part +and returns the next encrypted data part. (Depending on how data are +supplied, it may return more or less data than are supplied.) + +After all the parts are supplied, the application calls R_SealFinal, +giving the context. R_SealFinal returns the last encrypted data part. + +An application may call R_SealUpdate again after R_SealFinal to +encrypt other data under the same data encryption key and +initialization vector. This is useful when message content is signed +and encrypted, and the digital signature must also be encrypted. + + +R_SealInit + +int R_SealInit ( + R_ENVELOPE_CTX *context, /* new context */ + unsigned char **encryptedKeys, /* encrypted keys */ + unsigned int *encryptedKeyLens, /* lengths of encrypted keys */ + unsigned char iv[8], /* initialization vector */ + unsigned int publicKeyCount, /* number of public keys */ + R_RSA_PUBLIC_KEY **publicKeys, /* public keys */ + int encryptionAlgorithm, /* data encryption algorithm */ + R_RANDOM_STRUCT *randomStruct /* random structure */ +); + +R_SealInit begins a "sealing" operation. It performs the following +steps: + + 1. It sets up a new context. + + 2. It generates a random data encryption key and initialization + vector, storing the initialization vector in iv. + + 3. It encrypts the data encryption key with each recipient's + public key, storing the encrypted keys in encryptedKeys and + their lengths in encryptedKeyLens. (Note that each + encryptedKeys member should be a pointer, initialized by + the application.) + +The encryptedKeyLens members will not be greater than +MAX_ENCRYPTED_KEY_LEN. + +encryptionAlgorithm is the algorithm with which data are encrypted, +and must be one of the values listed in Appendix D. + +randomStruct must have been seeded. + +Return value: 0 success +RE_ENCRYPTION_ALGORITHM encryptionAlgorithm is invalid + RE_PUBLIC_KEY publicKey cannot encrypt data encryption + key + RE_NEED_RANDOM randomStruct is not seeded + + +R_SealUpdate + +int R_SealUpdate ( + R_ENVELOPE_CTX *context, /* context */ + unsigned char *partOut, /* next encrypted data part */ + unsigned int *partOutLen, /* length of next encrypted data part */ + unsigned char *partIn, /* next data part */ + unsigned int partInLen /* length of next data part */ +); + +R_SealUpdate continues a sealing operation, decrypting partIn, the +next data part, with the specified data encryption algorithm, and +returning partOut, the next encrypted data part. It may be called any +number of times. + +partOutLen will always be a multiple of 8, and it will not be greater +than partInLen+7. If partInLen is a multiple of 8, then partOutLen +will be the same as partInLen. + +(As a special case, if partInLen is a multiple of 24, then partOutLen +will be the same as partInLen; this is helpful when the output is to +be encoded in ASCII, since the length of each part input to +R_EncodePEMBlock should be a multiple of 3.) + +Return value: 0 success + + +R_SealFinal + +int R_SealFinal ( + R_ENVELOPE_CTX *context, /* context */ + unsigned char *partOut, /* last encrypted data part */ + unsigned int *partOutLen /* length of last encrypted data part */ +); + +R_SealFinal completes a sealing operation, returning partOut, the +last encrypted data part. + +partOutLen will always be 8. + +Return value: 0 success + + +3.4 Opening a digital envelope + +RSAREF opens digital envelopes with three procedures: R_OpenInit, +R_OpenUpdate, and R_OpenFinal. These procedures are typically called +by message-processing applications. + +An application first calls R_OpenInit, giving an integer specifying +which data encryption algorithm to apply (see Appendix D), an +initialization vector, the recipient's RSA private key, and an +encrypted data encryption key. R_OpenInit sets up a context for the +opening operation and decrypts the encrypted data encryption key with +the private key. It returns the context. + +The application then calls R_OpenUpdate any number of times, giving +the context and the next encrypted data part. R_OpenUpdate decrypts +the encrypted part and returns the next recovered data part. (Depending +on how data are supplied, it may return more or less data than are +supplied.) + +After all the parts are supplied, the application calls R_OpenFinal, +giving the context. R_OpenFinal returns the last recovered data part. + +As described for the sealing operations, an application may call +R_OpenUpdate again after R_OpenFinal to decrypt other data under the +same data encryption key and initialization vector. + + +R_OpenInit + +int R_OpenInit ( + R_ENVELOPE_CTX *context, /* new context */ + int encryptionAlgorithm, /* data encryption algorithm */ + unsigned char *encryptedKey, /* encrypted data encryption key */ + unsigned int encryptedKeyLen, /* length of encrypted key */ + unsigned char iv[8], /* initialization vector */ + R_RSA_PRIVATE_KEY *privateKey /* recipient's RSA private key */ +); + +R_OpenInit begins an "opening" operation, setting up a new context +and decrypting encryptedKey with privateKey. + +iv is the initialization vector for the data encryption algorithm. +encryptionAlgorithm is the algorithm with which the data is +encrypted, and must be one of the values listed in Appendix D. + +encryptedKeyLen must not be greater than MAX_ENCRYPTED_KEY_LEN. + +Return value: 0 success + RE_LEN encryptedKeyLen out of range +RE_ENCRYPTION_ALGORITHM encryptionAlgorithm is invalid + RE_PRIVATE_KEY privateKey cannot decrypt encrypted key + + +R_OpenUpdate + +int R_OpenUpdate ( + R_ENVELOPE_CTX *context, /* context */ + unsigned char *partOut, /* next recovered data part */ + unsigned int *partOutLen, /* length of next recovered data part */ + unsigned char *partIn, /* next encrypted data part */ + unsigned int partInLen /* length of next encrypted data part */ +); + +R_OpenUpdate continues an opening operation, decrypting partIn, the +next encrypted data part, and returning partOut, the next recovered +data part. It may be called any number of times. + +partOutLen will always be a multiple of 8, and it will not be greater +than partInLen+7. + +Return value: 0 success + + +R_OpenFinal + +int R_OpenFinal ( + R_ENVELOPE_CTX *context, /* context */ + unsigned char *partOut, /* last recovered data part */ + unsigned int *partOutLen /* length of last recovered data part */ +); + +R_SealFinal completes a sealing operation, returning partOut, the +last recovered data part. + +partOutLen will not be greater than 7. + +Return value: 0 success + RE_KEY recovered data encryption key cannot decrypt + encrypted data + +3.5 Digesting a message + +RSAREF digests messages with three procedures: R_DigestInit, +R_DigestUpdate, and R_DigestFinal. These procedures have no +particular PEM application, but may be useful in PKCS #7. + +An application first calls R_DigestInit, giving an integer specifying +which message-digest algorithm to apply (see Appendix D). +R_DigestInit sets up a context for the digesting operation, and +returns the context. + +The application then calls R_DigestUpdate any number of times, giving +the context and the next data part. R_DigestUpdate digests the part. + +After all the parts are supplied, the application calls +R_DigestFinal, giving the context. R_DigestFinal returns the message +digest. + +An application may call R_DigestUpdate again after R_DigestFinal to +digest other data, without setting up a new context. + + +R_DigestInit + +int R_DigestInit ( + R_DIGEST_CTX *context, /* new context */ + int digestAlgorithm /* message-digest algorithm */ +); + +R_DigestInit begins a message-digest operation, setting up a new +context. + +digestAlgorithm is the algorithm with which data are digested, and +must be one of the values listed in Appendix D. + +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + + +R_DigestUpdate + +int R_DigestUpdate ( + R_DIGEST_CTX *context, /* context */ + unsigned char *partIn, /* next data part */ + unsigned int partInLen /* length of next data part */ +); + +R_DigestUpdate continues a message-digest operation, digesting the +next data part with the specified message-digest algorithm. It may be +called any number of times. + +Return value: 0 success + + +R_DigestFinal + +int R_DigestFinal ( + R_DIGEST_CTX *context, /* context */ + unsigned char *digest, /* message digest */ + unsigned int *digestLen /* length of message digest */ +); + +R_DigestFinal completes a message-digest operation, storing the +message digest in digest and its length in bytes in digestLen. + +digestLen will not be greater than MAX_DIGEST_LEN. + +Return value: 0 success + + +4. ENCODING AND DECODING + +RSAREF encodes and decodes blocks of data in printable ASCII +according to RFC 1421 with two procedures: R_EncodePEMBlock +and R_DecodePEMBlock. They are typically called by +message-processing applications to format and parse fields +of the encapsulated header of a privacy-enhanced message, as +well as the message content. + +To encode a block in printable ASCII, an application calls +R_EncodePEMBlock, giving a pointer to the block and the block length. +R_EncodePEMBlock encodes the block in printable ASCII and returns the +encoded block. + +To decode a block encoded in printable ASCII, an application calls +R_DecodePEMBlock, giving a pointer to the encoded block, and the +encoded block length. R_DecodePEMBlock decodes the encoded block and +returns the decoded block. + +An application can process data in parts with these procedures, +provided that the length of each input part (except possibly the +last) is a multiple of the "quantum" size: three bytes for +encoding, four bytes for decoding. + -RSAREF applies cryptographic enhancements to messages with six -procedures: R_SignPEMBlock, R_VerifyPEMSignature, +R_EncodePEMBlock + +int R_EncodePEMBlock ( + unsigned char *encodedBlock, /* encoded block */ + unsigned int *encodedBlockLen, /* length of encoded block */ + unsigned char *block, /* block */ + unsigned int blockLen /* length of block */ +); + +R_EncodePEMBlock encodes block in printable ASCII according to RFC +1421, storing the encoding in encodedBlock. + +encodedBlock will be an ASCII string, encoded according to RFC 1421. +(It will not contain any line delimiters; the application must break +the string into lines.) encodedBlockLen will not be greater than +ENCODED_CONTENT_LEN(blockLen). + +When processing data in parts, blockLen should be a multiple of 3, +except possibly for the last part. + +Return value: 0 success + nonzero reserved for future compatibility + + +R_DecodePEMBlock + +int R_DecodePEMBlock (block, blockLen, encodedBlock, encodedBlockLen) + unsigned char *block, /* block */ + unsigned int *blockLen, /* length of block */ + unsigned char *encodedBlock, /* encoded block */ + unsigned int encodedBlockLen /* length of encoded block */ +); + +R_DecodePEMBlock decodes a block encoded according to RFC 1421. Its +operation is the reverse of R_EncodePEMBlock. + +blockLen will not be greater than +DECODED_CONTENT_LEN(encodedBlockLen). + +When processing data in parts, encodedBlockLen should be a multiple +of 4, except possibly for the last part. + +Return value: 0 success + RE_ENCODING encodedBlock has RFC 1421 encoding error + + +5. KEY-PAIR GENERATION + +RSAREF generates key pairs with the procedure R_GeneratePEMKeys. +R_GeneratePEMKeys is typically called by key generation applications. +To generate a new key pair, an application calls R_GeneratePEMKeys, +giving the length in bits of the modulus, the choice of public +exponent (3 or 65537), and a random structure. R_GeneratePEMKeys +generates an RSA key pair and returns the public and private keys. + + +R_GeneratePEMKeys + +int R_GeneratePEMKeys ( + R_RSA_PUBLIC_KEY *publicKey, /* new RSA public key */ + R_RSA_PRIVATE_KEY *privateKey, /* new RSA private key */ + R_RSA_PROTO_KEY *protoKey, /* RSA prototype key */ + R_RANDOM_STRUCT *randomStruct /* random structure */ +); + +R_GeneratePEMKeys generates a random RSA key pair, storing the +resulting RSA public key in publicKey and the resulting RSA private +key in privateKey. + +Other parameters are as follows: + + protoKey The RSA prototype key specifying the length + in bits of the RSA modulus and the public + exponent. (See Appendix B.) + + randomStruct Random structure from which the key pair is + derived. It must have been seeded. + +Return value: 0 success + RE_MODULUS_LEN modulus length invalid + RE_NEED_RANDOM randomStruct is not seeded + + +6. DIFFIE-HELLMAN KEY AGREEMENT + +To generate new Diffie-Hellman parameters, an application calls +R_GenerateDHParams, giving the length in bits of the Diffie-Hellman +prime and a random structure. R_GenerateDHParams generates the +parameters. Several users may share given Diffie-Hellman parameters, +or they may be unique to a given user. + +To set up a key agreement, communicating applications call +R_SetupDHAgreement, giving these parameters: + + - the Diffie-Hellman parameters + - a random structure + +R_SetupDHAgreement generates a new "public value" and a new "private +value" for each party. The applications then exchange their public +values. + +To compute the agreed-upon key, the applications call +R_ComputeDHAgreedKey, giving these parameters: + + - the Diffie-Hellman parameters + - the other party's public value + - the private value + +R_ComputeDHAgreedKey computes the agreed-upon key. + +The applications may encrypt subsequent data with the agreed-upon +key. When the length of the Diffie-Hellman prime is large enough, it +is considered impractical for someone who sees the Diffie-Hellman +parameters and the exchanged public values to determine to +agreed-upon key, so the subsequent encryption is secure. + + +R_GenerateDHParams + +int R_GenerateDHParams ( + R_DH_PARAMS *params, /* new Diffie-Hellman parameters */ + unsigned int primeBits, /* length in bits of prime */ + unsigned int subPrimeBits, /* length in bits of subprime */ + R_RANDOM_STRUCT *randomStruct /* random structure */ +); + +R_GenerateDHParams generates random Diffie-Hellman parameters, +storing the result in params. primeBits specifies the length in bits +of the Diffie-Hellman prime p, and subPrimeBits specifies the length +in bits of the prime q that divides p-1. The resulting generator g +has order q. + +The resulting params->primeLen and params->generatorLen will be at +most DH_PRIME_LEN (bits); params->prime and params->generator should +point to arrays at least that long. + +randomStruct must have been seeded. + +Return value: 0 success + RE_MODULUS_LEN prime length invalid + RE_NEED_RANDOM randomStruct is not seeded + + +R_SetupDHAgreement + +int R_SetupDHAgreement ( + unsigned char *publicValue, /* new public value */ + unsigned char *privateValue, /* new private value */ + unsigned int privateValueLen, /* length of private value */ + R_DH_PARAMS *params, /* Diffie-Hellman parameters */ + R_RANDOM_STRUCT *randomStruct /* random structure */ +); + +R_SetupDHAgreement sets up a Diffie-Hellman key agreement by +generating a public value and a private value from the Diffie-Hellman +parameters. It stores the resulting public value in publicValue and +the resulting private value in private value. + +The private value is a random number x whose length in bytes is +privateValueLen, and the public value is the number y such that + + y = g^x mod p, + +where p and g are the prime and generator in params. (Typically, one +selects privateValueLen according to the length in bits of the +"subprime" q.) + +publicValue and privateValue will be represented most significant +byte first, with no leading zero bytes. publicValue will have the +same length as the prime. + +randomStruct must have been seeded. + +Return value: 0 success + RE_NEED_RANDOM randomStruct is not seeded + + +R_ComputeDHAgreedKey + +int R_ComputeDHAgreedKey ( + unsigned char *agreedKey, /* new agreed-upon key */ + unsigned char *otherPublicValue, /* other's public value */ + unsigned char *privateValue, /* private value */ + unsigned int privateValueLen, /* length of private value */ + R_DH_PARAMS *params /* Diffie-Hellman parameters */ +); + +R_ComputeDHAgreedKey computes an agreed-upon key from the other +party's public value, a private value, and the Diffie-Hellman +parameters. It stores the resulting agreed key in agreedKey. + +The agreed key is the number z such that + + z = (y')^x mod p, + +where y' is the other party's public value, x is the private value, +and p is the prime in params. + +The other party's private value y' should be between 0 and p-1. + +agreedKey will be represented most significant byte first, with no +leading zero bytes. agreedKey will have the same length as the prime. + +Return value: 0 success + RE_DATA other party's private value out of range + + +7. VERSION 1.0 ROUTINES + +The following procedures are retained for backward compatibility with +RSAREF 1.0: R_SignPEMBlock, R_SignBlock, R_VerifyPEMSignature, R_VerifyBlockSignature, R_SealPEMBlock, R_OpenPEMBlock, and R_DigestBlock. -The first five procedures are typically called by message-processing -applications. R_DigestBlock is typically called by key-generation -applications when computing the message digest of a prototype -certificate [2,9]. +The procedures are typically called by message-processing +applications. R_SignBlock is also typically called by key-generation +applications when constructing a PEM or PKCS certification request, +and by certification applications when signing a certificate. +R_DigestBlock has no particular PEM application, but may be useful in +PKCS #7. To sign a message, an application calls R_SignPEMBlock, giving these arguments: - a pointer to the message content, and the message length - an integer identifying which message-digest algorithm to apply - (MD2 or MD5) + (see Appendix D) - a flag indicating whether to encode the message in printable - ASCII according to RFC 1113 + ASCII according to RFC 1421 - the signer's RSA private key R_SignPEMBlock signs the message with the signer's private key and the specified message-digest algorithm, and optionally encodes the -message in printable ASCII. It returns the signature, possibly the -encoded message, and the status of the operation. The signature is -encoded according to RFC 1113. +message in printable ASCII. It returns the signature and possibly the +encoded message. The signature is encoded according to RFC 1421. + +To sign a block of data such as a certificate where the signature is +not encoded in printable ASCII, an application calls R_SignBlock, +giving these arguments: + + - a pointer to the block, and the block length + - an integer identifying which message-digest algorithm to apply + (see Appendix D) + - the signer's RSA private key + +R_SignBlock signs the message with the signer's private key and the +specified message-digest algorithm. It returns the signature. To verify a signature on a message, an application calls R_VerifyPEMSignature, giving these arguments: @@ -177,7 +901,7 @@ R_VerifyPEMSignature, giving these argum length - a pointer to the signature, and the signature length - an integer identifying which message-digest algorithm was applied - (MD2 or MD5) + (see Appendix D) - a flag indicating whether the message was encoded in printable ASCII - the signer's RSA public key @@ -185,7 +909,7 @@ R_VerifyPEMSignature, giving these argum R_VerifyPEMSignature decodes the message if it was encoded and verifies the signature on the message with the signer's public key and the specified message-digest algorithm. It returns the message -content if the message was encoded, and the status of the operation. +content if the message was encoded. To verify a signature on a block of data such as a certificate where the signature is not encoded in printable ASCII, an application calls @@ -194,29 +918,29 @@ R_VerifyBlockSignature, giving these arg - a pointer to the block, and the block length - a pointer to the signature, and the signature length - an integer identifying which message-digest algorithm was applied - (MD2 or MD5) + (see Appendix D) - the signer's RSA public key R_VerifyBlockSignature verifies the signature on the message with the -signer's public key and the specified message-digest algorithm. It -returns the status of the operation. +signer's public key and the specified message-digest algorithm. -To seal a message (sign and encrypt it), an application calls -R_SealPEMBlock, giving these arguments: +To sign and encrypt a message, an application calls R_SealPEMBlock, +giving these arguments: - a pointer to the message content, and the message length - an integer identifying which message-digest algorithm to apply - (MD2 or MD5) + (see Appendix D) - the signer's RSA private key - the recipient's RSA public key + - a random structure R_SealPEMBlock signs the message with the signer's private key and the specified message-digest algorithm, encrypts the message and the signature with a random DES key, and encrypts the DES key with the recipient's public key. It returns the encrypted message, the -encrypted key, the encrypted signature, the DES initialization -vector, and the status of the operation. The encrypted message, key, -and signature are encoded according to RFC 1113. +encrypted key, the encrypted signature, and the DES initialization +vector. The encrypted message, key, and signature are encoded +according to RFC 1421. To open a message (decrypt it and verify its signature), an application calls R_OpenPEMBlock, giving these arguments: @@ -228,7 +952,7 @@ application calls R_OpenPEMBlock, giving length - a DES initialization vector - an integer identifying which message-digest algorithm was applied - (MD2 or MD5) + (see Appendix D) - the signer's RSA public key - the recipient's RSA private key @@ -236,19 +960,17 @@ R_OpenPEMBlock decrypts the encrypted DE private key, decrypts the encrypted message and the encrypted signature with the DES key, and verifies the signature on the message with the signer's public key and the specified message-digest -algorithm. It returns the message content and the status of the -operation. +algorithm. It returns the message content. To digest a block of data such as a prototype certificate, an application calls R_DigestBlock, giving these arguments: - a pointer to the block, and the block length - an integer identifying which message-digest algorithm to apply - (MD2 or MD5) + (see Appendix D) R_DigestBlock digests the block with the specified message-digest -algorithm. It returns the message digest and the status of the -operation. +algorithm. It returns the message digest. ENCODED_CONTENT_LEN, DECODED_CONTENT_LEN, ENCRYPTED_CONTENT_LEN, and DECRYPTED_CONTENT_LEN are macros that assist in determining the @@ -272,35 +994,57 @@ int R_SignPEMBlock ( R_SignPEMBlock computes a digital signature on content. Specifically, R_SignPEMBlock performs the following steps: - 1. It digests content with digestAlgorithm, giving a message + 1. It digests content with digestAlgorithm, giving a message digest. - 2. It encrypts the message digest with privateKey, giving a + 2. It encrypts the message digest with privateKey, giving a digital signature, and encodes the result in printable - ASCII according to RFC 1113, storing the encoding in + ASCII according to RFC 1421, storing the encoding in encodedSignature. 3. If recode is nonzero, it encodes content in printable ASCII, storing the encoding in encodedContent. If recode is nonzero, encodedContent will be an ASCII string, encoded -according to RFC 1113. (It will not contain any line delimiters; the +according to RFC 1421. (It will not contain any line delimiters; the application must break the string into 64-character lines.) encodedContentLen will not be greater than ENCODED_CONTENT_LEN(contentLen). If recode is zero, encodedContent is ignored. encodedSignature will be an ASCII string, encoded according to RFC -1113. encodedSignatureLen will not be greater than +1421. encodedSignatureLen will not be greater than MAX_PEM_SIGNATURE_LEN. -digestAlgorithm is the algorithm by which the content is digested. It -must be DA_MD2, which indicates the MD2 message-digest algorithm, or -DA_MD5, which indicates the MD5 message-digest algorithm. +digestAlgorithm is the algorithm with which the message content is +digested, and must be one of the values listed in Appendix D. -Return value: 0 success - RE_DIGEST_ALGORITHM digestAlgorithm is invalid - RE_PRIVATE_KEY privateKey cannot encrypt message digest +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_PRIVATE_KEY privateKey cannot encrypt message digest + + +R_SignBlock + +int R_SignBlock ( + unsigned char *signature, /* encoded signature */ + unsigned int *signatureLen, /* length of encoded signature */ + unsigned char *block, /* block */ + unsigned int blockLen, /* length of block */ + int digestAlgorithm, /* message-digest algorithm */ + R_RSA_PRIVATE_KEY *privateKey /* signer's RSA private key */ +); + +R_SignBlock computes a digital signature on block of data such as a +certificate. Its operation is similar to R_SignPEMBlock, except that +the resulting signature is an arbitrary byte string, rather than an +RFC 1421-encoded string. + +signatureLen will not be greater than MAX_SIGNATURE_LEN. + +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_PRIVATE_KEY privateKey cannot encrypt message digest R_VerifyPEMSignature @@ -320,18 +1064,18 @@ int R_VerifyPEMSignature ( R_VerifyPEMSignature verifies a digital signature on a message. Its operation is the inverse of R_SignPEMBlock. R_VerifyPEMSignature operates on encodedSignature and encodedContent. If recode is -nonzero, it first decodes encodedContent according to RFC 1113, and +nonzero, it first decodes encodedContent according to RFC 1421, and stores the result in content. If recode is zero, content is ignored. If recode is nonzero, contentLen will not be greater than DECODED_CONTENT_LEN(encodedContentLen). -Return value: 0 success - RE_CONTENT_ENCODING encodedContent has RFC 1113 encoding error -RE_SIGNATURE_ENCODING encodedSignature has RFC 1113 encoding error - RE_DIGEST_ALGORITHM digestAlgorithm is invalid - RE_PUBLIC_KEY publicKey cannot decrypt signature - RE_SIGNATURE signature on content is incorrect +Return value: 0 success + RE_CONTENT_ENCODING encodedContent has RFC 1421 encoding error +RE_SIGNATURE_ENCODING encodedSignature has RFC 1421 encoding error + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_PUBLIC_KEY publicKey cannot decrypt signature + RE_SIGNATURE signature on content is incorrect R_VerifyBlockSignature @@ -348,12 +1092,12 @@ int R_VerifyBlockSignature ( R_VerifyBlockSignature verifies a digital signature on a block of data such as a certificate. Its operation is similar to R_VerifyPEMSignature, except that the block and signature are -arbitrary byte strings, rather than RFC 1113-encoded strings. +arbitrary byte strings, rather than RFC 1421-encoded strings. -Return value: 0 success - RE_DIGEST_ALGORITHM digestAlgorithm is invalid - RE_PUBLIC_KEY publicKey cannot decrypt signature - RE_SIGNATURE signature on block is incorrect +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_PUBLIC_KEY publicKey cannot decrypt signature + RE_SIGNATURE signature on block is incorrect R_SealPEMBlock @@ -368,7 +1112,7 @@ int R_SealPEMBlock ( unsigned char *encryptedSignature,/* encoded, encrypted signature */ unsigned int *encryptedSignatureLen, /* length of encoded, encrypted signature */ - unsigned char iv[8], /* DES initializing vector */ + unsigned char iv[8], /* DES initialization vector */ unsigned char *content, /* content */ unsigned int contentLen, /* length of content */ int digestAlgorithm, /* message-digest algorithm */ @@ -381,49 +1125,48 @@ R_SealPEMBlock computes a digital signat the content and the signature. Specifically, R_SealPEMBlock performs the following steps: - 1. It digests content with digestAlgorithm, giving a message + 1. It digests content with digestAlgorithm, giving a message digest. - 2. It encrypts the message digest with privateKey, giving a + 2. It encrypts the message digest with privateKey, giving a digital signature. - 3. It generates a random DES key and initializing vector, - storing the initializing vector in iv. + 3. It generates a random DES key and initialization vector, + storing the initialization vector in iv. - 4. It encrypts content with the DES key and initializing vector + 4. It encrypts content with the DES key and initialization vector in cipher-block chaining mode, and encodes the result in - printable ASCII according to RFC 1113, storing the encoding + printable ASCII according to RFC 1421, storing the encoding in encryptedContent. - 5. It encrypts the DES key with publicKey and encodes the + 5. It encrypts the DES key with publicKey and encodes the result in printable ASCII, storing the encoding in encryptedKey. - 6. It encrypts the digital signature with the DES key and - initializing vector, and encodes the result in printable + 6. It encrypts the digital signature with the DES key and + initialization vector, and encodes the result in printable ASCII, storing the encoding in encryptedSignature. encryptedContent will be an ASCII string, encoded according to RFC -1113. (It will not contain any line delimiters; the application must +1421. (It will not contain any line delimiters; the application must break the string into 64-character lines.) encryptedContentLen will not be greater than ENCRYPTED_CONTENT_LEN(contentLen). encryptedKey and encryptedSignature will be ASCII strings, encoded -according to RFC 1113. encryptedKeyLen will not be greater than +according to RFC 1421. encryptedKeyLen will not be greater than MAX_PEM_ENCRYPTED_KEY_LEN. encryptedSignatureLen will not be greater than MAX_PEM_ENCRYPTED_SIGNATURE_LEN. -digestAlgorithm is the algorithm by which the content is digested. It -must be DA_MD2, which indicates the MD2 message-digest algorithm, or -DA_MD5, which indicates the MD5 message-digest algorithm. +digestAlgorithm is the algorithm with which the message content is +digested, and must be one of the values listed in Appendix D. randomStruct must have been seeded. -Return value: 0 success - RE_DIGEST_ALGORITHM digestAlgorithm is invalid - RE_PRIVATE_KEY privateKey cannot encrypt message digest - RE_PUBLIC_KEY publicKey cannot encrypt DES key - RE_NEED_RANDOM randomStruct is not seeded +Return value: 0 success + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_PRIVATE_KEY privateKey cannot encrypt message digest + RE_PUBLIC_KEY publicKey cannot encrypt DES key + RE_NEED_RANDOM randomStruct is not seeded R_OpenPEMBlock @@ -440,7 +1183,7 @@ int R_OpenPEMBlock ( unsigned char *encryptedSignature,/* encoded, encrypted signature */ unsigned int encryptedSignatureLen, /* length of encoded, encrypted signature */ - unsigned char iv[8], /* DES initializing vector */ + unsigned char iv[8], /* DES initialization vector */ int digestAlgorithm, /* message-digest algorithm */ R_RSA_PRIVATE_KEY *privateKey, /* recipient's RSA private key */ R_RSA_PUBLIC_KEY *publicKey /* signer's RSA public key */ @@ -453,16 +1196,16 @@ contentLen will not be greater than DECRYPTED_CONTENT_LEN(encryptedContentLen). Return value: 0 success - RE_CONTENT_ENCODING encryptedContent has RFC 1113 encoding error - RE_KEY_ENCODING encryptedKey has RFC 1113 encoding error -RE_SIGNATURE_ENCODING encryptedSignature has RFC 1113 encoding + RE_CONTENT_ENCODING encryptedContent has RFC 1421 encoding error + RE_KEY_ENCODING encryptedKey has RFC 1421 encoding error +RE_SIGNATURE_ENCODING encryptedSignature has RFC 1421 encoding error - RE_PUBLIC_KEY publicKey cannot decrypt signature - RE_PRIVATE_KEY privateKey cannot decrypt encrypted key - RE_KEY recovered DES key cannot decrypt encrypted + RE_PUBLIC_KEY publicKey cannot decrypt signature + RE_PRIVATE_KEY privateKey cannot decrypt encrypted key + RE_KEY recovered DES key cannot decrypt encrypted content or encrypted signature - RE_DIGEST_ALGORITHM digestAlgorithm is invalid - RE_SIGNATURE signature on content is incorrect + RE_DIGEST_ALGORITHM digestAlgorithm is invalid + RE_SIGNATURE signature on content is incorrect R_DigestBlock @@ -475,12 +1218,12 @@ int R_DigestBlock ( int digestAlgorithm /* message-digest algorithm */ ); -R_DigestBlock computes a message digest on content, storing the -resulting message digest in digest and its length in digestLen. +R_DigestBlock computes the message digest of content, storing the +resulting message digest in digest and its length in bytes in +digestLen. -digestAlgorithm is the algorithm by which the content is digested. It -must be DA_MD2, which indicates the MD2 message-digest algorithm, or -DA_MD5, which indicates the MD5 message-digest algorithm. +digestAlgorithm is the algorithm with which the content is digested, +and must be one of the values in Appendix D. digestLen will not be greater than MAX_DIGEST_LEN. @@ -488,44 +1231,7 @@ Return value: 0 success RE_DIGEST_ALGORITHM digestAlgorithm is invalid -KEY-PAIR GENERATION - -RSAREF generates key pairs with the procedure R_GeneratePEMKeys. -R_GeneratePEMKeys is typically called by key generation applications. -To generate a new key pair, an application calls R_GeneratePEMKeys, -giving the length of the modulus, the choice of exponent (F4 or F0), -and a random structure. R_GeneratePEMKeys generates an RSA key pair -and returns the status of the operation. - - -R_GeneratePEMKeys - -int R_GeneratePEMKeys ( - R_RSA_PUBLIC_KEY *publicKey, /* new RSA public key */ - R_RSA_PRIVATE_KEY *privateKey, /* new RSA private key */ - R_RSA_PROTO_KEY *protoKey, /* RSA prototype key */ - R_RANDOM_STRUCT *randomStruct /* random structure */ -); - -R_GeneratePEMKeys generates a random RSA key pair, storing the -resulting RSA public key in publicKey and the resulting RSA private -key in privateKey. - -Other parameters are as follows: - - protoKey The RSA prototype key specifying the length - in bits of the RSA modulus and the public - exponent. (See Appendix B.) - - randomStruct Random structure from which the key pair is - derived. It must have been seeded. - -Return value: 0 success - RE_MODULUS_LEN modulus length invalid - RE_NEED_RANDOM randomStruct is not seeded - - -RUN-TIME LIBRARY +8. RUN-TIME LIBRARY RSAREF operates on memory blocks with three platform-specific library procedures that are modeled after conventional C library functions: @@ -591,36 +1297,45 @@ APPENDIX A: RSAREF ERROR TYPES This appendix lists RSAREF's error types. - RE_CONTENT_ENCODING content or encrypted content has RFC 1113 - encoding error + RE_DATA other party's private value out of range + + RE_CONTENT_ENCODING content, encrypted content, or encoded block + has RFC 1421 encoding error - RE_DIGEST_ALGORITHM message-digest algorithm is invalid + RE_DIGEST_ALGORITHM message-digest algorithm is invalid - RE_KEY recovered DES key cannot decrypt encrypted + RE_ENCODING encoded block has RFC 1421 encoding error + +RE_ENCRYPTION_ALGORITHM encryption algorithm is invalid + + RE_KEY recovered DES key cannot decrypt encrypted content or encrypted signature - RE_KEY_ENCODING encrypted key has RFC 1113 encoding error + RE_KEY_ENCODING encrypted key has RFC 1421 encoding error + + RE_LEN encrypted key length or signature length + out of range - RE_MODULUS_LEN modulus length is invalid + RE_MODULUS_LEN modulus length out of range - RE_NEED_RANDOM random structure is not seeded + RE_NEED_RANDOM random structure is not seeded - RE_PRIVATE_KEY private key cannot encrypt message digest, + RE_PRIVATE_KEY private key cannot encrypt message digest, or cannot decrypt encrypted key - RE_PUBLIC_KEY public key cannot encrypt DES key, or cannot - decrypt signature + RE_PUBLIC_KEY public key cannot encrypt data encryption + key, or cannot decrypt signature - RE_SIGNATURE signature on content or block is incorrect + RE_SIGNATURE signature on content or block is incorrect -RE_SIGNATURE_ENCODING signature or encrypted signature has RFC 1113 +RE_SIGNATURE_ENCODING signature or encrypted signature has RFC 1421 encoding error APPENDIX B: RSAREF TYPES -This appendix lists three RSAREF types: R_RSA_PUBLIC_KEY, -R_RSA_PRIVATE_KEY, and R_RSA_PROTO_KEY. +This appendix lists four RSAREF types: R_RSA_PUBLIC_KEY, +R_RSA_PRIVATE_KEY, R_RSA_PROTO_KEY, and R_DH_PARAMS. R_RSA_PUBLIC_KEY @@ -693,8 +1408,6 @@ key. There are seven fields: R_RSA_PROTO_KEY -/* RSA prototype key. - */ typedef struct { unsigned int bits; /* length in bits of modulus */ int useFermat4; /* public exponent (1 = F4, 0 = 3) */ @@ -713,6 +1426,29 @@ There are two fields: (3) +R_DH_PARAMS + +typedef struct { + unsigned char *prime; /* prime */ + unsigned int primeLen; /* length of prime */ + unsigned char *generator; /* generator */ + unsigned int generatorLen; /* length of generator */ +} R_DH_PARAMS; + +An R_DH_PARAMS value is a structure specifying Diffie-Hellman +parameters. There are four fields: + + prime prime p, represented as a primeLen-byte + number, most significant byte first, as + many leading zero bytes as necessary + + primeLen length in bytes of the prime + + generator generator g, represented like prime + + generatorLen length in bytes of the generator + + APPENDIX C: PLATFORM-SPECIFIC TYPES AND CONSTANTS This appendix lists three platform-specific types and one #define'd @@ -768,39 +1504,97 @@ Otherwise declarations take the form type function (); +APPENDIX D: ENCRYPTION ALGORITHMS AND IDENTIFIERS + +This appendix lists message-digest and data encryption algorithms and +their identifiers. + + +D.1 Message-digest algorithms + +RSAREF supports two message-digest algorithms, listed here with their +integer identifiers: + + DA_MD2 MD2 message-digest algorithm [3] + + DA_MD5 MD5 message-digest algorithm [4] + + +D.2 Data encryption algorithms + +RSAREF supports four data encryption algorithms, listed here with +their integer identifiers: + + EA_DES_CBC Data Encryption Standard [5] in cipher-block + chaining (CBC) mode [6] + + EA_DESX_CBC RSA Data Security's DESX enhancement of DES, + in CBC mode (this algorithm exclusive-ors + with the previous ciphertext block, + exclusive-ors with a secret value, encrypts + with DES, then exclusive-ors with a second + secret value) + + EA_DES_EDE3_CBC Three-key triple-DES in CBC mode (this + algorithm exclusive-ORs with the previous + ciphertext block, encrypts with one DES + key, decrypts with a second DES key, then + encrypts with a third DES key) + + EA_DES_EDE2_CBC Two-key triple-DES in CBC mode (like three- + key, except that the first and third DES + keys are the same) + +All four algorithms have a block size of eight bytes, and hence an +eight-byte initialization vector. All employ the padding rules +described in RFC 1423 [11]. + + REFERENCES -[1] J. Linn. RFC 1113: Privacy Enhancement for Internet Electronic - Mail: Part I -- Message Encipherment and Authentication - Procedures. Internet Activities Board, August 1989. - -[2] S. Kent and J. Linn. RFC 1114: Privacy Enhancement for Internet - Electronic Mail: Part II -- Certificate-Based Key Management. - Internet Activities Board, August 1989. - -[3] J. Linn. RFC 1115: Privacy Enhancement for Internet Electronic - Mail: Part III -- Algorithms, Modes, and Identifiers. Internet - Activities Board, August 1989. - -[4] RSA Data Security, Inc. PKCS #1: RSA Encryption Standard. Version - 1.4, June 1991. Also published as NIST/OSI Implementors Workshop - SEC-SIG-91-18, June 1991. (Available by anonymous FTP from - 'rsa.com' as 'pub/pkcs/pkcs-1.ps'.) - -[5] B.S. Kaliski Jr. The MD2 Message-Digest Algorithm. July 1, 1991. - (Available by anonymous FTP from 'rsa.com' as 'pub/md2.doc'.) - -[6] Ronald L. Rivest. The MD5 Message-Digest Algorithm. In - preparation. (Earlier version available by anonymous FTP from - 'rsa.com' as 'pub/md5.doc'.) +[1] R.L. Rivest, A. Shamir, and L. Adleman. A method for obtaining + digital signatures and public-key cryptosystems. Communications + of the ACM, 21(2):120-126, February 1978. + +[2] RSA Laboratories. PKCS #1: RSA Encryption Standard. Version 1.5, + November 1993. (PKCS documents are available via electronic mail + to .) + +[3] B. Kaliski. RFC 1319: The MD2 Message-Digest Algorithm. April + 1992. -[7] National Bureau of Standards. FIPS Publication 46-1: Data +[4] R. Rivest. RFC 1321: The MD5 Message-Digest Algorithm. April + 1992. + +[5] National Bureau of Standards. FIPS Publication 46-1: Data Encryption Standard. January 1988. -[8] National Bureau of Standards. FIPS Publication 81: DES Modes of +[6] National Bureau of Standards. FIPS Publication 81: DES Modes of Operation. December 1980. -[9] B.S. Kaliski Jr. Privacy Enhancement for Internet Electronic - Mail: Part IV: Notary, Co-Issuer, CRL-Storing, and - CRL-Retrieving Services. Draft, July 1, 1991. (Available by - anonymous FTP from 'rsa.com' as 'pub/forms.doc'.) +[7] W. Diffie and M.E. Hellman. New directions in cryptography. IEEE + Transactions on Information Theory, IT-22:644-654, 1976. + +[8] RSA Laboratories. PKCS #3: Diffie-Hellman Key-Agreement Standard. + Version 1.4, November 1993. + +[9] J. Linn. RFC 1421: Privacy Enhancement for Internet Electronic + Mail: Part I: Message Encryption and Authentication Procedures. + February 1993. + +[10] S. Kent. RFC 1422: Privacy Enhancement for Internet Electronic + Mail: Part II: Certificate-Based Key Management. February 1993. + +[11] D. Balenson. RFC 1423: Privacy Enhancement for Internet + Electronic Mail: Part III: Algorithms, Modes, and Identifiers. + February 1993. + +[12] B. Kaliski. RFC 1424: Privacy Enhancement for Internet Electronic + Mail: Part IV: Key Certification and Related Services. February + 1993. + +[13] RSA Laboratories. PKCS #7: Cryptographic Message Syntax Standard. + Version 1.5, November 1993. + +[14] RSA Laboratories. PKCS #10: Certification Request Syntax + Standard. Version 1.0, November 1993.