Annotation of pgp/rsaref/doc/rsaref.txt, revision 1.1

1.1     ! root        1:                  RSAREF(TM): A Cryptographic Toolkit
        !             2:                        Library Reference Manual
        !             3: 
        !             4:                            RSA Laboratories
        !             5:                             March 21, 1994
        !             6: 
        !             7:                              Version 2.0
        !             8: 
        !             9:     Copyright (C) 1991-4 RSA Laboratories, a division of RSA Data
        !            10:                  Security, Inc. All rights reserved.
        !            11: 
        !            12: 
        !            13: 1. INTRODUCTION
        !            14: 
        !            15: This manual is a reference guide for users of RSAREF, RSA
        !            16: Laboratories' portable, educational, reference implementation of
        !            17: cryptography.
        !            18: 
        !            19: RSAREF supports the following algorithms:
        !            20: 
        !            21:      o    RSA encryption and key generation [1], as defined by RSA
        !            22:           Laboratories' Public-Key Cryptography Standards (PKCS) [2]
        !            23: 
        !            24:      o    MD2 and MD5 message digests [3,4]
        !            25: 
        !            26:      o    DES (Data Encryption Standard) in cipher-block chaining mode
        !            27:           [5,6]
        !            28: 
        !            29:      o    Diffie-Hellman key agreement [7], as defined by PKCS #3 [8]
        !            30: 
        !            31:      o    DESX, RSA Data Security's efficient, secure DES enhancement
        !            32: 
        !            33:      o    Triple-DES, for added security with three DES operations
        !            34: 
        !            35: RSAREF is written entirely in C. Its application interface includes
        !            36: the following routines:
        !            37: 
        !            38:          R_SignInit,     computes a digital signature on data of
        !            39:        R_SignUpdate,       arbitrary length, processing in parts
        !            40:      and R_SignFinal
        !            41: 
        !            42:        R_VerifyInit,     verifies a digital signature, processing in
        !            43:      R_VerifyUpdate,       parts
        !            44:    and R_VerifyFinal
        !            45: 
        !            46:          R_SealInit,     creates a digital envelope on data of
        !            47:        R_SealUpdate,       arbitrary length, processing in parts
        !            48:      and R_SealFinal
        !            49: 
        !            50:          R_OpenInit,     opens a digital envelope, processing in
        !            51:        R_OpenUpdate,       parts
        !            52:      and R_OpenFinal
        !            53: 
        !            54:        R_DigestInit,     digests data of arbitrary length, processing
        !            55:      R_DigestUpdate,       in parts
        !            56:    and R_DigestFinal
        !            57: 
        !            58:     R_EncodePEMBlock     encodes a message in printable ASCII
        !            59:                            according to RFC 1421 [9]
        !            60:     R_DecodePEMBlock     decodes a message encoded according to RFC
        !            61:                            1421
        !            62: 
        !            63:    R_GeneratePEMKeys     generates an RSA public/private key pair
        !            64: 
        !            65:         R_RandomInit     initializes a random structure
        !            66:       R_RandomUpdate     mixes bytes into a random structure
        !            67: R_GetRandomBytesNeeded   computes the number of mix-in bytes still
        !            68:                            needed to seed a random structure
        !            69:        R_RandomFinal     zeroizes a random structure
        !            70: 
        !            71:   R_GenerateDHParams     generates Diffie-Hellman parameters
        !            72:   R_SetupDHAgreement     sets up a key agreement
        !            73:  R_ComputeDHAgreedKey    computes the agreed-upon key
        !            74: 
        !            75: An Internet Privacy-Enhanced Mail [9-12] implementation can be built
        !            76: directly on top of these routines, together with message parsing and
        !            77: formatting routines and certificate-management routines.
        !            78: Implementations of PKCS #7 and #10 [13,14] can be built in a similar
        !            79: manner. Other secure applications can be built on top of the
        !            80: Diffie-Hellman routines.
        !            81: 
        !            82: The following routines are supported for backward compatibility with
        !            83: RSAREF 1.0:
        !            84: 
        !            85:       R_SignPEMBlock     computes a digital signature on a message
        !            86:          R_SignBlock     computes a digital signature on a block of
        !            87:                            data such as a certificate
        !            88: R_VerifyPEMSignature     verifies a digital signature on a message
        !            89: R_VerifyBlockSignature   verifies a digital signature on a block of
        !            90:                            data such as a certificate
        !            91: 
        !            92:       R_SealPEMBlock     computes a digital signature and encrypts a
        !            93:                            message
        !            94:       R_OpenPEMBlock     decrypts an encrypted message and verifies a
        !            95:                            digital signature
        !            96: 
        !            97:        R_DigestBlock     computes the message digest of a message
        !            98: 
        !            99: This manual is divided into eight sections and three appendices.
        !           100: 
        !           101: This section introduces RSAREF. The next six sections explain RSAREF
        !           102: procedures: random structures; cryptographic enhancements; printable
        !           103: ASCII encoding and decoding; key-pair generation; Diffie-Hellman key
        !           104: agreement; and version 1.0 routines. The last section documents the
        !           105: platform-specific run-time library.
        !           106: 
        !           107: Appendix A lists RSAREF error types. Appendix B lists RSAREF types
        !           108: and constants. Appendix C lists platform-specific types and
        !           109: constants.
        !           110: 
        !           111: 
        !           112: 2. RANDOM STRUCTURES
        !           113: 
        !           114: A random structure contains a seed from which a pseudorandom sequence
        !           115: of bytes is derived. RSAREF generates keys and pads RSA encryption
        !           116: blocks with bytes derived from a random structure.
        !           117: 
        !           118: Random structures are used by both message-processing and
        !           119: key-generation applications.
        !           120: 
        !           121: RSAREF sets up a random structure with the procedure R_RandomInit. A
        !           122: typical application calls R_RandomInit on entry.
        !           123: 
        !           124: A new random structure is not ready for use until it is seeded by
        !           125: mixing in some random bytes. RSAREF seeds a random structure with the
        !           126: procedure R_RandomUpdate and R_GetRandomBytesNeeded. A random
        !           127: structure is considered seeded when the number of bytes still needed
        !           128: reaches zero. More bytes can be mixed in after the random structure
        !           129: is seeded. A typical application calls R_GetRandomBytesNeeded and
        !           130: R_RandomUpdate immediately after calling R_RandomInit.
        !           131: 
        !           132: RSAREF zeroizes a random structure with the procedure R_RandomFinal.
        !           133: A typical application calls R_RandomFinal on exit.
        !           134: 
        !           135: 
        !           136: R_RandomInit
        !           137: 
        !           138: int R_RandomInit (
        !           139:   R_RANDOM_STRUCT *randomStruct             /* new random structure */
        !           140: );
        !           141: 
        !           142: R_RandomInit sets up a new random structure.
        !           143: 
        !           144: Return value:      0     success
        !           145:              nonzero     reserved for future compatibility
        !           146: 
        !           147: 
        !           148: R_RandomUpdate
        !           149: 
        !           150: int R_RandomUpdate (
        !           151:   R_RANDOM_STRUCT *randomStruct,                /* random structure */
        !           152:   unsigned char *block,                /* block of values to mix in */
        !           153:   unsigned int blockLen                          /* length of block */
        !           154: );
        !           155: 
        !           156: R_RandomUpdate mixes blockLen bytes from block into randomStruct.
        !           157: 
        !           158: Return value:      0     success
        !           159:              nonzero     reserved for future compatibility
        !           160: 
        !           161: 
        !           162: R_GetRandomBytesNeeded
        !           163: 
        !           164: int R_GetRandomBytesNeeded (
        !           165:   unsigned int *bytesNeeded,       /* number of mix-in bytes needed */
        !           166:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !           167: );
        !           168: 
        !           169: R_GetRandomBytesNeeded computes the number of mix-in bytes still
        !           170: needed to seed randomStruct, storing the result in bytesNeeded.
        !           171: 
        !           172: Return value:      0     success
        !           173:              nonzero     reserved for future compatibility
        !           174: 
        !           175: 
        !           176: R_RandomFinal
        !           177: 
        !           178: void R_RandomFinal (
        !           179:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !           180: );
        !           181: 
        !           182: R_RandomFinal zeroizes randomStruct.
        !           183: 
        !           184: No return value.
        !           185: 
        !           186: 
        !           187: 3. CRYPTOGRAPHIC ENHANCEMENTS
        !           188: 
        !           189: RSAREF's cryptographic enhancements fall into five groups: signing
        !           190: data; verifying signatures; sealing data in digital envelopes;
        !           191: opening digital envelopes; and digesting data.
        !           192: 
        !           193: All the procedures process data in parts; it is not necessary for all
        !           194: data to be stored in memory at once.
        !           195: 
        !           196: 
        !           197: 3.1 Signing data
        !           198: 
        !           199: RSAREF signs data with three procedures: R_SignInit, R_SignUpdate,
        !           200: and R_SignFinal. These procedures are typically called by
        !           201: message-processing applications, by key-generation applications when
        !           202: constructing a PEM or PKCS certification request, and by
        !           203: certification applications when signing a certificate.
        !           204: 
        !           205: An application first calls R_SignInit, giving an integer specifying
        !           206: which message-digest algorithm to apply (see Appendix D). R_SignInit
        !           207: sets up a context for the signature operation, and returns the
        !           208: context.
        !           209: 
        !           210: The application then calls R_SignUpdate any number of times, giving
        !           211: the context and the next data part. R_SignUpdate digests the part.
        !           212: 
        !           213: After all the parts are supplied, the application calls R_SignFinal,
        !           214: giving the context and the signer's RSA private key. R_SignFinal
        !           215: encrypts the message digest with the private key and returns the
        !           216: result, which is the signature.
        !           217: 
        !           218: An application may call R_SignUpdate again after R_SignFinal to
        !           219: sign other data, without setting up a new context.
        !           220: 
        !           221: 
        !           222: R_SignInit
        !           223: 
        !           224: int R_SignInit (
        !           225:   R_SIGNATURE_CTX *context,                          /* new context */
        !           226:   int digestAlgorithm                   /* message-digest algorithm */
        !           227: );
        !           228: 
        !           229: R_SignInit begins a signature operation, setting up a new context.
        !           230: 
        !           231: digestAlgorithm is the algorithm with which data are digested, and
        !           232: must be one of the values listed in Appendix D.
        !           233: 
        !           234: Return value:      0     success
        !           235:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !           236: 
        !           237: 
        !           238: R_SignUpdate
        !           239: 
        !           240: int R_SignUpdate (
        !           241:   R_SIGNATURE_CTX *context,                              /* context */
        !           242:   unsigned char *partIn,                          /* next data part */
        !           243:   unsigned char partInLen               /* length of next data part */
        !           244: );
        !           245: 
        !           246: R_SignUpdate continues a signature operation, digesting partIn, the
        !           247: next data part, with the specified message-digest algorithm. It may
        !           248: be called any number of times.
        !           249: 
        !           250: Return value:      0     success
        !           251: 
        !           252: 
        !           253: R_SignFinal
        !           254: 
        !           255: int R_SignFinal (
        !           256:   R_SIGNATURE_CTX *context,                              /* context */
        !           257:   unsigned char *signature,                            /* signature */
        !           258:   unsigned int *signatureLen,                /* length of signature */
        !           259:   R_RSA_PRIVATE_KEY *privateKey         /* signer's RSA private key */
        !           260: );
        !           261: 
        !           262: R_SignFinal completes a signature operation, encrypting the message
        !           263: digest with the signer's private key. It stores the resulting
        !           264: signature in signature and its length in signatureLen.
        !           265: 
        !           266: signatureLen will not be greater than MAX_SIGNATURE_LEN.
        !           267: 
        !           268: Return value:      0     success
        !           269:       RE_PRIVATE_KEY     privateKey cannot encrypt message digest
        !           270: 
        !           271: 
        !           272: 3.2 Verifying a signature
        !           273: 
        !           274: RSAREF verifies signatures with three procedures: R_VerifyInit,
        !           275: R_VerifyUpdate, and R_VerifyFinal. These procedures are typically
        !           276: called by message-processing applications and by certification
        !           277: applications when processing a certification request.
        !           278: 
        !           279: An application first calls R_VerifyInit, giving an integer specifying
        !           280: which message-digest algorithm to apply (see Appendix D).
        !           281: R_VerifyInit sets up a context for the verification operation, and
        !           282: returns the context.
        !           283: 
        !           284: The application then calls R_VerifyUpdate any number of times, giving
        !           285: the context and the next data part. R_VerifyUpdate digests the part.
        !           286: 
        !           287: After all the parts are supplied, the application calls
        !           288: R_VerifyFinal, giving the context, the signer's RSA public key, and
        !           289: the signature. R_SignFinal decrypts the signature with the public key
        !           290: and compares the result to the message digest to see whether the
        !           291: signature is valid.
        !           292: 
        !           293: An application may call R_VerifyUpdate again after R_VerifyFinal to
        !           294: verify other signatures, without setting up a new context.
        !           295: 
        !           296: 
        !           297: R_VerifyInit
        !           298: 
        !           299: int R_VerifyInit (
        !           300:   R_SIGNATURE_CTX *context,                          /* new context */
        !           301:   int digestAlgorithm                   /* message-digest algorithm */
        !           302: );
        !           303: 
        !           304: R_VerifyInit begins a verification operation, setting up a new
        !           305: context.
        !           306: 
        !           307: digestAlgorithm is the algorithm with which data are digested, and
        !           308: must be one of the values listed in Appendix D.
        !           309: 
        !           310: Return value:      0     success
        !           311:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !           312: 
        !           313: 
        !           314: R_VerifyUpdate
        !           315: 
        !           316: int R_VerifyUpdate (
        !           317:   R_SIGNATURE_CTX *context,                              /* context */
        !           318:   unsigned char *partIn,                          /* next data part */
        !           319:   unsigned int partInLen                /* length of next data part */
        !           320: );
        !           321: 
        !           322: R_VerifyUpdate continues a verification operation, digesting partIn,
        !           323: the next data part, with the specified message-digest algorithm. It
        !           324: may be called any number of times.
        !           325: 
        !           326: Return value:      0     success
        !           327: 
        !           328: 
        !           329: R_VerifyFinal
        !           330: 
        !           331: int R_VerifyFinal (
        !           332:   R_SIGNATURE_CTX *context,                              /* context */
        !           333:   unsigned char *signature,                            /* signature */
        !           334:   unsigned int signatureLen,                 /* length of signature */
        !           335:   R_RSA_PUBLIC_KEY *publicKey            /* signer's RSA public key */
        !           336: );
        !           337: 
        !           338: R_VerifyFinal completes a verification operation, decrypting the
        !           339: signature with the signer's public key and comparing it to the
        !           340: message digest.
        !           341: 
        !           342: signatureLen must not be greater than MAX_SIGNATURE_LEN.
        !           343: 
        !           344: Return value:      0     success
        !           345:               RE_LEN     signatureLen out of range
        !           346:        RE_PUBLIC_KEY     publicKey cannot decrypt signature
        !           347:         RE_SIGNATURE     signature is incorrect
        !           348: 
        !           349: 
        !           350: 3.3 Sealing data in a digital envelope
        !           351: 
        !           352: RSAREF seals data in digital envelopes with three procedures:
        !           353: R_SealInit, R_SealUpdate, and R_SealFinal. There may be any number of
        !           354: recipients. These procedures are typically called by
        !           355: message-processing applications.
        !           356: 
        !           357: An application first calls R_SealInit, giving an integer specifying
        !           358: which data encryption algorithm to apply (see Appendix D), the public
        !           359: key of each recipient, and a random structure. R_SealInit sets up a
        !           360: context for the sealing operation, generates a data encryption key
        !           361: and an initialization vector, and encrypts the data encryption key
        !           362: with each recipient's public key.  It returns the context, the
        !           363: initialization vector, and the encrypted data encryption keys.
        !           364: 
        !           365: The application then calls R_SealUpdate any number of times, giving
        !           366: the context and the next data part. R_SealUpdate encrypts the part
        !           367: and returns the next encrypted data part. (Depending on how data are
        !           368: supplied, it may return more or less data than are supplied.)
        !           369: 
        !           370: After all the parts are supplied, the application calls R_SealFinal,
        !           371: giving the context. R_SealFinal returns the last encrypted data part.
        !           372: 
        !           373: An application may call R_SealUpdate again after R_SealFinal to
        !           374: encrypt other data under the same data encryption key and
        !           375: initialization vector. This is useful when message content is signed
        !           376: and encrypted, and the digital signature must also be encrypted.
        !           377: 
        !           378: 
        !           379: R_SealInit
        !           380: 
        !           381: int R_SealInit (
        !           382:   R_ENVELOPE_CTX *context,                                /* new context */
        !           383:   unsigned char **encryptedKeys,                       /* encrypted keys */
        !           384:   unsigned int *encryptedKeyLens,           /* lengths of encrypted keys */
        !           385:   unsigned char iv[8],                          /* initialization vector */
        !           386:   unsigned int publicKeyCount,                  /* number of public keys */
        !           387:   R_RSA_PUBLIC_KEY **publicKeys,                          /* public keys */
        !           388:   int encryptionAlgorithm,                  /* data encryption algorithm */
        !           389:   R_RANDOM_STRUCT *randomStruct                      /* random structure */
        !           390: );
        !           391: 
        !           392: R_SealInit begins a "sealing" operation. It performs the following
        !           393: steps:
        !           394: 
        !           395:     1.   It sets up a new context.
        !           396: 
        !           397:     2.   It generates a random data encryption key and initialization
        !           398:          vector, storing the initialization vector in iv.
        !           399: 
        !           400:     3.   It encrypts the data encryption key with each recipient's
        !           401:          public key, storing the encrypted keys in encryptedKeys and
        !           402:          their lengths in encryptedKeyLens. (Note that each
        !           403:          encryptedKeys member should be a pointer, initialized by
        !           404:          the application.)
        !           405:          
        !           406: The encryptedKeyLens members will not be greater than
        !           407: MAX_ENCRYPTED_KEY_LEN.
        !           408: 
        !           409: encryptionAlgorithm is the algorithm with which data are encrypted,
        !           410: and must be one of the values listed in Appendix D.
        !           411: 
        !           412: randomStruct must have been seeded.
        !           413: 
        !           414: Return value:      0     success
        !           415: RE_ENCRYPTION_ALGORITHM  encryptionAlgorithm is invalid
        !           416:        RE_PUBLIC_KEY     publicKey cannot encrypt data encryption
        !           417:                            key
        !           418:       RE_NEED_RANDOM     randomStruct is not seeded
        !           419: 
        !           420: 
        !           421: R_SealUpdate
        !           422: 
        !           423: int R_SealUpdate (
        !           424:   R_ENVELOPE_CTX *context,                               /* context */
        !           425:   unsigned char *partOut,               /* next encrypted data part */
        !           426:   unsigned int *partOutLen,   /* length of next encrypted data part */
        !           427:   unsigned char *partIn,                          /* next data part */
        !           428:   unsigned int partInLen                /* length of next data part */
        !           429: );
        !           430: 
        !           431: R_SealUpdate continues a sealing operation, decrypting partIn, the
        !           432: next data part, with the specified data encryption algorithm, and
        !           433: returning partOut, the next encrypted data part. It may be called any
        !           434: number of times.
        !           435: 
        !           436: partOutLen will always be a multiple of 8, and it will not be greater
        !           437: than partInLen+7. If partInLen is a multiple of 8, then partOutLen
        !           438: will be the same as partInLen.
        !           439: 
        !           440: (As a special case, if partInLen is a multiple of 24, then partOutLen
        !           441: will be the same as partInLen; this is helpful when the output is to
        !           442: be encoded in ASCII, since the length of each part input to
        !           443: R_EncodePEMBlock should be a multiple of 3.)
        !           444: 
        !           445: Return value:      0     success
        !           446: 
        !           447: 
        !           448: R_SealFinal
        !           449: 
        !           450: int R_SealFinal (
        !           451:   R_ENVELOPE_CTX *context,                               /* context */
        !           452:   unsigned char *partOut,               /* last encrypted data part */
        !           453:   unsigned int *partOutLen    /* length of last encrypted data part */
        !           454: );
        !           455: 
        !           456: R_SealFinal completes a sealing operation, returning partOut, the
        !           457: last encrypted data part.
        !           458: 
        !           459: partOutLen will always be 8.
        !           460: 
        !           461: Return value:      0     success
        !           462: 
        !           463: 
        !           464: 3.4 Opening a digital envelope
        !           465: 
        !           466: RSAREF opens digital envelopes with three procedures: R_OpenInit,
        !           467: R_OpenUpdate, and R_OpenFinal. These procedures are typically called
        !           468: by message-processing applications.
        !           469: 
        !           470: An application first calls R_OpenInit, giving an integer specifying
        !           471: which data encryption algorithm to apply (see Appendix D), an
        !           472: initialization vector, the recipient's RSA private key, and an
        !           473: encrypted data encryption key. R_OpenInit sets up a context for the
        !           474: opening operation and decrypts the encrypted data encryption key with
        !           475: the private key. It returns the context.
        !           476: 
        !           477: The application then calls R_OpenUpdate any number of times, giving
        !           478: the context and the next encrypted data part. R_OpenUpdate decrypts
        !           479: the encrypted part and returns the next recovered data part. (Depending
        !           480: on how data are supplied, it may return more or less data than are
        !           481: supplied.)
        !           482: 
        !           483: After all the parts are supplied, the application calls R_OpenFinal,
        !           484: giving the context. R_OpenFinal returns the last recovered data part.
        !           485: 
        !           486: As described for the sealing operations, an application may call
        !           487: R_OpenUpdate again after R_OpenFinal to decrypt other data under the
        !           488: same data encryption key and initialization vector.
        !           489: 
        !           490: 
        !           491: R_OpenInit
        !           492: 
        !           493: int R_OpenInit (
        !           494:   R_ENVELOPE_CTX *context,                                /* new context */
        !           495:   int encryptionAlgorithm,                  /* data encryption algorithm */
        !           496:   unsigned char *encryptedKey,          /* encrypted data encryption key */
        !           497:   unsigned int encryptedKeyLen,               /* length of encrypted key */
        !           498:   unsigned char iv[8],                          /* initialization vector */
        !           499:   R_RSA_PRIVATE_KEY *privateKey           /* recipient's RSA private key */
        !           500: );
        !           501: 
        !           502: R_OpenInit begins an "opening" operation, setting up a new context
        !           503: and decrypting encryptedKey with privateKey.
        !           504: 
        !           505: iv is the initialization vector for the data encryption algorithm.
        !           506: encryptionAlgorithm is the algorithm with which the data is
        !           507: encrypted, and must be one of the values listed in Appendix D.
        !           508: 
        !           509: encryptedKeyLen must not be greater than MAX_ENCRYPTED_KEY_LEN.
        !           510: 
        !           511: Return value:      0     success
        !           512:               RE_LEN     encryptedKeyLen out of range
        !           513: RE_ENCRYPTION_ALGORITHM  encryptionAlgorithm is invalid
        !           514:       RE_PRIVATE_KEY     privateKey cannot decrypt encrypted key
        !           515: 
        !           516: 
        !           517: R_OpenUpdate
        !           518: 
        !           519: int R_OpenUpdate (
        !           520:   R_ENVELOPE_CTX *context,                               /* context */
        !           521:   unsigned char *partOut,               /* next recovered data part */
        !           522:   unsigned int *partOutLen,   /* length of next recovered data part */
        !           523:   unsigned char *partIn,                /* next encrypted data part */
        !           524:   unsigned int partInLen      /* length of next encrypted data part */
        !           525: );
        !           526: 
        !           527: R_OpenUpdate continues an opening operation, decrypting partIn, the
        !           528: next encrypted data part, and returning partOut, the next recovered
        !           529: data part. It may be called any number of times.
        !           530: 
        !           531: partOutLen will always be a multiple of 8, and it will not be greater
        !           532: than partInLen+7.
        !           533: 
        !           534: Return value:      0     success
        !           535: 
        !           536: 
        !           537: R_OpenFinal
        !           538: 
        !           539: int R_OpenFinal (
        !           540:   R_ENVELOPE_CTX *context,                               /* context */
        !           541:   unsigned char *partOut,               /* last recovered data part */
        !           542:   unsigned int *partOutLen    /* length of last recovered data part */
        !           543: );
        !           544: 
        !           545: R_SealFinal completes a sealing operation, returning partOut, the
        !           546: last recovered data part.
        !           547: 
        !           548: partOutLen will not be greater than 7.
        !           549: 
        !           550: Return value:      0     success
        !           551:               RE_KEY     recovered data encryption key cannot decrypt
        !           552:                            encrypted data
        !           553: 
        !           554: 3.5 Digesting a message
        !           555: 
        !           556: RSAREF digests messages with three procedures: R_DigestInit,
        !           557: R_DigestUpdate, and R_DigestFinal. These procedures have no
        !           558: particular PEM application, but may be useful in PKCS #7.
        !           559: 
        !           560: An application first calls R_DigestInit, giving an integer specifying
        !           561: which message-digest algorithm to apply (see Appendix D).
        !           562: R_DigestInit sets up a context for the digesting operation, and
        !           563: returns the context.
        !           564: 
        !           565: The application then calls R_DigestUpdate any number of times, giving
        !           566: the context and the next data part. R_DigestUpdate digests the part.
        !           567: 
        !           568: After all the parts are supplied, the application calls
        !           569: R_DigestFinal, giving the context. R_DigestFinal returns the message
        !           570: digest.
        !           571: 
        !           572: An application may call R_DigestUpdate again after R_DigestFinal to
        !           573: digest other data, without setting up a new context.
        !           574: 
        !           575: 
        !           576: R_DigestInit
        !           577: 
        !           578: int R_DigestInit (
        !           579:   R_DIGEST_CTX *context,                             /* new context */
        !           580:   int digestAlgorithm                   /* message-digest algorithm */
        !           581: );
        !           582: 
        !           583: R_DigestInit begins a message-digest operation, setting up a new
        !           584: context.
        !           585: 
        !           586: digestAlgorithm is the algorithm with which data are digested, and
        !           587: must be one of the values listed in Appendix D.
        !           588: 
        !           589: Return value:      0     success
        !           590:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !           591: 
        !           592: 
        !           593: R_DigestUpdate
        !           594: 
        !           595: int R_DigestUpdate (
        !           596:   R_DIGEST_CTX *context,                                 /* context */
        !           597:   unsigned char *partIn,                          /* next data part */
        !           598:   unsigned int partInLen                /* length of next data part */
        !           599: );
        !           600: 
        !           601: R_DigestUpdate continues a message-digest operation, digesting the
        !           602: next data part with the specified message-digest algorithm. It may be
        !           603: called any number of times.
        !           604: 
        !           605: Return value:      0     success
        !           606: 
        !           607: 
        !           608: R_DigestFinal
        !           609: 
        !           610: int R_DigestFinal (
        !           611:   R_DIGEST_CTX *context,                                 /* context */
        !           612:   unsigned char *digest,                          /* message digest */
        !           613:   unsigned int *digestLen               /* length of message digest */
        !           614: );
        !           615: 
        !           616: R_DigestFinal completes a message-digest operation, storing the
        !           617: message digest in digest and its length in bytes in digestLen.
        !           618: 
        !           619: digestLen will not be greater than MAX_DIGEST_LEN.
        !           620: 
        !           621: Return value:      0     success
        !           622: 
        !           623: 
        !           624: 4. ENCODING AND DECODING
        !           625: 
        !           626: RSAREF encodes and decodes blocks of data in printable ASCII
        !           627: according to RFC 1421 with two procedures: R_EncodePEMBlock
        !           628: and R_DecodePEMBlock. They are typically called by
        !           629: message-processing applications to format and parse fields
        !           630: of the encapsulated header of a privacy-enhanced message, as
        !           631: well as the message content.
        !           632: 
        !           633: To encode a block in printable ASCII, an application calls
        !           634: R_EncodePEMBlock, giving a pointer to the block and the block length.
        !           635: R_EncodePEMBlock encodes the block in printable ASCII and returns the
        !           636: encoded block.
        !           637: 
        !           638: To decode a block encoded in printable ASCII, an application calls
        !           639: R_DecodePEMBlock, giving a pointer to the encoded block, and the
        !           640: encoded block length. R_DecodePEMBlock decodes the encoded block and
        !           641: returns the decoded block.
        !           642: 
        !           643: An application can process data in parts with these procedures,
        !           644: provided that the length of each input part (except possibly the
        !           645: last) is a multiple of the "quantum" size: three bytes for
        !           646: encoding, four bytes for decoding.
        !           647: 
        !           648: 
        !           649: R_EncodePEMBlock
        !           650: 
        !           651: int R_EncodePEMBlock (
        !           652:   unsigned char *encodedBlock,                     /* encoded block */
        !           653:   unsigned int *encodedBlockLen,         /* length of encoded block */
        !           654:   unsigned char *block,                                    /* block */
        !           655:   unsigned int blockLen                          /* length of block */
        !           656: );
        !           657: 
        !           658: R_EncodePEMBlock encodes block in printable ASCII according to RFC
        !           659: 1421, storing the encoding in encodedBlock.
        !           660: 
        !           661: encodedBlock will be an ASCII string, encoded according to RFC 1421.
        !           662: (It will not contain any line delimiters; the application must break
        !           663: the string into lines.) encodedBlockLen will not be greater than
        !           664: ENCODED_CONTENT_LEN(blockLen).
        !           665: 
        !           666: When processing data in parts, blockLen should be a multiple of 3,
        !           667: except possibly for the last part.
        !           668: 
        !           669: Return value:      0     success
        !           670:              nonzero     reserved for future compatibility
        !           671: 
        !           672: 
        !           673: R_DecodePEMBlock
        !           674: 
        !           675: int R_DecodePEMBlock (block, blockLen, encodedBlock, encodedBlockLen)
        !           676:   unsigned char *block,                                    /* block */
        !           677:   unsigned int *blockLen,                        /* length of block */
        !           678:   unsigned char *encodedBlock,                     /* encoded block */
        !           679:   unsigned int encodedBlockLen           /* length of encoded block */
        !           680: );
        !           681: 
        !           682: R_DecodePEMBlock decodes a block encoded according to RFC 1421. Its
        !           683: operation is the reverse of R_EncodePEMBlock.
        !           684: 
        !           685: blockLen will not be greater than
        !           686: DECODED_CONTENT_LEN(encodedBlockLen).
        !           687: 
        !           688: When processing data in parts, encodedBlockLen should be a multiple
        !           689: of 4, except possibly for the last part.
        !           690: 
        !           691: Return value:      0     success
        !           692:          RE_ENCODING     encodedBlock has RFC 1421 encoding error
        !           693: 
        !           694: 
        !           695: 5. KEY-PAIR GENERATION
        !           696: 
        !           697: RSAREF generates key pairs with the procedure R_GeneratePEMKeys.
        !           698: R_GeneratePEMKeys is typically called by key generation applications.
        !           699: To generate a new key pair, an application calls R_GeneratePEMKeys,
        !           700: giving the length in bits of the modulus, the choice of public
        !           701: exponent (3 or 65537), and a random structure. R_GeneratePEMKeys
        !           702: generates an RSA key pair and returns the public and private keys.
        !           703: 
        !           704: 
        !           705: R_GeneratePEMKeys
        !           706: 
        !           707: int R_GeneratePEMKeys (
        !           708:   R_RSA_PUBLIC_KEY *publicKey,                /* new RSA public key */
        !           709:   R_RSA_PRIVATE_KEY *privateKey,             /* new RSA private key */
        !           710:   R_RSA_PROTO_KEY *protoKey,                   /* RSA prototype key */
        !           711:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !           712: );
        !           713: 
        !           714: R_GeneratePEMKeys generates a random RSA key pair, storing the
        !           715: resulting RSA public key in publicKey and the resulting RSA private
        !           716: key in privateKey.
        !           717: 
        !           718: Other parameters are as follows:
        !           719: 
        !           720:             protoKey     The RSA prototype key specifying the length
        !           721:                            in bits of the RSA modulus and the public
        !           722:                            exponent. (See Appendix B.)
        !           723: 
        !           724:         randomStruct     Random structure from which the key pair is
        !           725:                            derived. It must have been seeded.
        !           726: 
        !           727: Return value:      0     success
        !           728:       RE_MODULUS_LEN     modulus length invalid
        !           729:       RE_NEED_RANDOM     randomStruct is not seeded
        !           730: 
        !           731: 
        !           732: 6. DIFFIE-HELLMAN KEY AGREEMENT
        !           733: 
        !           734: To generate new Diffie-Hellman parameters, an application calls
        !           735: R_GenerateDHParams, giving the length in bits of the Diffie-Hellman
        !           736: prime and a random structure. R_GenerateDHParams generates the
        !           737: parameters. Several users may share given Diffie-Hellman parameters,
        !           738: or they may be unique to a given user.
        !           739: 
        !           740: To set up a key agreement, communicating applications call
        !           741: R_SetupDHAgreement, giving these parameters:
        !           742: 
        !           743:   -  the Diffie-Hellman parameters
        !           744:   -  a random structure
        !           745: 
        !           746: R_SetupDHAgreement generates a new "public value" and a new "private
        !           747: value" for each party. The applications then exchange their public
        !           748: values.
        !           749: 
        !           750: To compute the agreed-upon key, the applications call
        !           751: R_ComputeDHAgreedKey, giving these parameters:
        !           752: 
        !           753:   -  the Diffie-Hellman parameters
        !           754:   -  the other party's public value
        !           755:   -  the private value
        !           756: 
        !           757: R_ComputeDHAgreedKey computes the agreed-upon key.
        !           758: 
        !           759: The applications may encrypt subsequent data with the agreed-upon
        !           760: key. When the length of the Diffie-Hellman prime is large enough, it
        !           761: is considered impractical for someone who sees the Diffie-Hellman
        !           762: parameters and the exchanged public values to determine to
        !           763: agreed-upon key, so the subsequent encryption is secure.
        !           764: 
        !           765: 
        !           766: R_GenerateDHParams
        !           767: 
        !           768: int R_GenerateDHParams (
        !           769:   R_DH_PARAMS *params,             /* new Diffie-Hellman parameters */
        !           770:   unsigned int primeBits,               /* length in bits of prime  */
        !           771:   unsigned int subPrimeBits,         /* length in bits of subprime  */
        !           772:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !           773: );
        !           774: 
        !           775: R_GenerateDHParams generates random Diffie-Hellman parameters,
        !           776: storing the result in params. primeBits specifies the length in bits
        !           777: of the Diffie-Hellman prime p, and subPrimeBits specifies the length
        !           778: in bits of the prime q that divides p-1. The resulting generator g
        !           779: has order q.
        !           780: 
        !           781: The resulting params->primeLen and params->generatorLen will be at
        !           782: most DH_PRIME_LEN (bits); params->prime and params->generator should
        !           783: point to arrays at least that long.
        !           784: 
        !           785: randomStruct must have been seeded.
        !           786: 
        !           787: Return value:      0     success
        !           788:       RE_MODULUS_LEN     prime length invalid
        !           789:       RE_NEED_RANDOM     randomStruct is not seeded
        !           790: 
        !           791: 
        !           792: R_SetupDHAgreement
        !           793: 
        !           794: int R_SetupDHAgreement (
        !           795:   unsigned char *publicValue,                   /* new public value */
        !           796:   unsigned char *privateValue,                 /* new private value */
        !           797:   unsigned int privateValueLen,          /* length of private value */
        !           798:   R_DH_PARAMS *params,                 /* Diffie-Hellman parameters */
        !           799:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !           800: );
        !           801: 
        !           802: R_SetupDHAgreement sets up a Diffie-Hellman key agreement by
        !           803: generating a public value and a private value from the Diffie-Hellman
        !           804: parameters. It stores the resulting public value in publicValue and
        !           805: the resulting private value in private value.
        !           806: 
        !           807: The private value is a random number x whose length in bytes is
        !           808: privateValueLen, and the public value is the number y such that
        !           809: 
        !           810:                             y = g^x mod p,
        !           811: 
        !           812: where p and g are the prime and generator in params. (Typically, one
        !           813: selects privateValueLen according to the length in bits of the
        !           814: "subprime" q.)
        !           815: 
        !           816: publicValue and privateValue will be represented most significant
        !           817: byte first, with no leading zero bytes. publicValue will have the
        !           818: same length as the prime.
        !           819: 
        !           820: randomStruct must have been seeded.
        !           821: 
        !           822: Return value:      0     success
        !           823:       RE_NEED_RANDOM     randomStruct is not seeded
        !           824: 
        !           825: 
        !           826: R_ComputeDHAgreedKey
        !           827: 
        !           828: int R_ComputeDHAgreedKey (
        !           829:   unsigned char *agreedKey,                  /* new agreed-upon key */
        !           830:   unsigned char *otherPublicValue,          /* other's public value */
        !           831:   unsigned char *privateValue,                     /* private value */
        !           832:   unsigned int privateValueLen,          /* length of private value */
        !           833:   R_DH_PARAMS *params                  /* Diffie-Hellman parameters */
        !           834: );
        !           835: 
        !           836: R_ComputeDHAgreedKey computes an agreed-upon key from the other
        !           837: party's public value, a private value, and the Diffie-Hellman
        !           838: parameters. It stores the resulting agreed key in agreedKey.
        !           839: 
        !           840: The agreed key is the number z such that
        !           841: 
        !           842:                             z = (y')^x mod p,
        !           843: 
        !           844: where y' is the other party's public value, x is the private value,
        !           845: and p is the prime in params.
        !           846: 
        !           847: The other party's private value y' should be between 0 and p-1.
        !           848: 
        !           849: agreedKey will be represented most significant byte first, with no
        !           850: leading zero bytes. agreedKey will have the same length as the prime.
        !           851: 
        !           852: Return value:      0     success
        !           853:              RE_DATA     other party's private value out of range
        !           854: 
        !           855: 
        !           856: 7. VERSION 1.0 ROUTINES
        !           857: 
        !           858: The following procedures are retained for backward compatibility with
        !           859: RSAREF 1.0: R_SignPEMBlock, R_SignBlock, R_VerifyPEMSignature,
        !           860: R_VerifyBlockSignature, R_SealPEMBlock, R_OpenPEMBlock, and
        !           861: R_DigestBlock.
        !           862: 
        !           863: The procedures are typically called by message-processing
        !           864: applications. R_SignBlock is also typically called by key-generation
        !           865: applications when constructing a PEM or PKCS certification request,
        !           866: and by certification applications when signing a certificate.
        !           867: R_DigestBlock has no particular PEM application, but may be useful in
        !           868: PKCS #7.
        !           869: 
        !           870: To sign a message, an application calls R_SignPEMBlock, giving these
        !           871: arguments:
        !           872: 
        !           873:   -  a pointer to the message content, and the message length
        !           874:   -  an integer identifying which message-digest algorithm to apply
        !           875:        (see Appendix D)
        !           876:   -  a flag indicating whether to encode the message in printable
        !           877:        ASCII according to RFC 1421
        !           878:   -  the signer's RSA private key
        !           879: 
        !           880: R_SignPEMBlock signs the message with the signer's private key and
        !           881: the specified message-digest algorithm, and optionally encodes the
        !           882: message in printable ASCII. It returns the signature and possibly the
        !           883: encoded message. The signature is encoded according to RFC 1421.
        !           884: 
        !           885: To sign a block of data such as a certificate where the signature is
        !           886: not encoded in printable ASCII, an application calls R_SignBlock,
        !           887: giving these arguments:
        !           888: 
        !           889:   -  a pointer to the block, and the block length
        !           890:   -  an integer identifying which message-digest algorithm to apply
        !           891:        (see Appendix D)
        !           892:   -  the signer's RSA private key
        !           893: 
        !           894: R_SignBlock signs the message with the signer's private key and the
        !           895: specified message-digest algorithm. It returns the signature.
        !           896: 
        !           897: To verify a signature on a message, an application calls
        !           898: R_VerifyPEMSignature, giving these arguments:
        !           899: 
        !           900:   -  a pointer to the (possibly encoded) message, and the message
        !           901:        length
        !           902:   -  a pointer to the signature, and the signature length
        !           903:   -  an integer identifying which message-digest algorithm was applied
        !           904:        (see Appendix D)
        !           905:   -  a flag indicating whether the message was encoded in printable
        !           906:        ASCII
        !           907:   -  the signer's RSA public key
        !           908: 
        !           909: R_VerifyPEMSignature decodes the message if it was encoded and
        !           910: verifies the signature on the message with the signer's public key
        !           911: and the specified message-digest algorithm. It returns the message
        !           912: content if the message was encoded.
        !           913: 
        !           914: To verify a signature on a block of data such as a certificate where
        !           915: the signature is not encoded in printable ASCII, an application calls
        !           916: R_VerifyBlockSignature, giving these arguments:
        !           917: 
        !           918:   -  a pointer to the block, and the block length
        !           919:   -  a pointer to the signature, and the signature length
        !           920:   -  an integer identifying which message-digest algorithm was applied
        !           921:        (see Appendix D)
        !           922:   -  the signer's RSA public key
        !           923: 
        !           924: R_VerifyBlockSignature verifies the signature on the message with the
        !           925: signer's public key and the specified message-digest algorithm.
        !           926: 
        !           927: To sign and encrypt a message, an application calls R_SealPEMBlock,
        !           928: giving these arguments:
        !           929: 
        !           930:   -  a pointer to the message content, and the message length
        !           931:   -  an integer identifying which message-digest algorithm to apply
        !           932:        (see Appendix D)
        !           933:   -  the signer's RSA private key
        !           934:   -  the recipient's RSA public key
        !           935:   -  a random structure
        !           936: 
        !           937: R_SealPEMBlock signs the message with the signer's private key and
        !           938: the specified message-digest algorithm, encrypts the message and the
        !           939: signature with a random DES key, and encrypts the DES key with the
        !           940: recipient's public key. It returns the encrypted message, the
        !           941: encrypted key, the encrypted signature, and the DES initialization
        !           942: vector. The encrypted message, key, and signature are encoded
        !           943: according to RFC 1421.
        !           944: 
        !           945: To open a message (decrypt it and verify its signature), an
        !           946: application calls R_OpenPEMBlock, giving these arguments:
        !           947: 
        !           948:   -  a pointer to the encrypted message, and the encrypted message
        !           949:        length
        !           950:   -  a pointer to the encrypted key, and the encrypted key length
        !           951:   -  a pointer to the encrypted signature, and the encrypted signature
        !           952:        length
        !           953:   -  a DES initialization vector
        !           954:   -  an integer identifying which message-digest algorithm was applied
        !           955:        (see Appendix D)
        !           956:   -  the signer's RSA public key
        !           957:   -  the recipient's RSA private key
        !           958: 
        !           959: R_OpenPEMBlock decrypts the encrypted DES key with the recipient's
        !           960: private key, decrypts the encrypted message and the encrypted
        !           961: signature with the DES key, and verifies the signature on the message
        !           962: with the signer's public key and the specified message-digest
        !           963: algorithm. It returns the message content.
        !           964: 
        !           965: To digest a block of data such as a prototype certificate, an
        !           966: application calls R_DigestBlock, giving these arguments:
        !           967: 
        !           968:   -  a pointer to the block, and the block length
        !           969:   -  an integer identifying which message-digest algorithm to apply
        !           970:        (see Appendix D)
        !           971: 
        !           972: R_DigestBlock digests the block with the specified message-digest
        !           973: algorithm. It returns the message digest.
        !           974: 
        !           975: ENCODED_CONTENT_LEN, DECODED_CONTENT_LEN, ENCRYPTED_CONTENT_LEN, and
        !           976: DECRYPTED_CONTENT_LEN are macros that assist in determining the
        !           977: maximum lengths of the results of cryptographic enhancements.
        !           978: 
        !           979: 
        !           980: R_SignPEMBlock
        !           981: 
        !           982: int R_SignPEMBlock (
        !           983:   unsigned char *encodedContent,                 /* encoded content */
        !           984:   unsigned int *encodedContentLen,     /* length of encoded content */
        !           985:   unsigned char *encodedSignature,             /* encoded signature */
        !           986:   unsigned int *encodedSignatureLen, /* length of encoded signature */
        !           987:   unsigned char *content,                                /* content */ 
        !           988:   unsigned int contentLen,                     /* length of content */ 
        !           989:   int recode,                                      /* recoding flag */
        !           990:   int digestAlgorithm,                  /* message-digest algorithm */
        !           991:   R_RSA_PRIVATE_KEY *privateKey         /* signer's RSA private key */
        !           992: );
        !           993: 
        !           994: R_SignPEMBlock computes a digital signature on content. Specifically,
        !           995: R_SignPEMBlock performs the following steps:
        !           996: 
        !           997:      1.   It digests content with digestAlgorithm, giving a message
        !           998:           digest.
        !           999: 
        !          1000:      2.   It encrypts the message digest with privateKey, giving a
        !          1001:           digital signature, and encodes the result in printable
        !          1002:           ASCII according to RFC 1421, storing the encoding in
        !          1003:           encodedSignature.
        !          1004: 
        !          1005:     3.    If recode is nonzero, it encodes content in printable ASCII,
        !          1006:           storing the encoding in encodedContent.
        !          1007: 
        !          1008: If recode is nonzero, encodedContent will be an ASCII string, encoded
        !          1009: according to RFC 1421. (It will not contain any line delimiters; the
        !          1010: application must break the string into 64-character lines.)
        !          1011: encodedContentLen will not be greater than
        !          1012: ENCODED_CONTENT_LEN(contentLen). If recode is zero, encodedContent is
        !          1013: ignored.
        !          1014: 
        !          1015: encodedSignature will be an ASCII string, encoded according to RFC
        !          1016: 1421. encodedSignatureLen will not be greater than
        !          1017: MAX_PEM_SIGNATURE_LEN.
        !          1018: 
        !          1019: digestAlgorithm is the algorithm with which the message content is
        !          1020: digested, and must be one of the values listed in Appendix D.
        !          1021: 
        !          1022: Return value:      0     success
        !          1023:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1024:       RE_PRIVATE_KEY     privateKey cannot encrypt message digest
        !          1025: 
        !          1026: 
        !          1027: R_SignBlock
        !          1028: 
        !          1029: int R_SignBlock (
        !          1030:   unsigned char *signature,                    /* encoded signature */
        !          1031:   unsigned int *signatureLen,        /* length of encoded signature */
        !          1032:   unsigned char *block,                                    /* block */ 
        !          1033:   unsigned int blockLen,                         /* length of block */ 
        !          1034:   int digestAlgorithm,                  /* message-digest algorithm */
        !          1035:   R_RSA_PRIVATE_KEY *privateKey         /* signer's RSA private key */
        !          1036: );
        !          1037: 
        !          1038: R_SignBlock computes a digital signature on block of data such as a
        !          1039: certificate. Its operation is similar to R_SignPEMBlock, except that
        !          1040: the resulting signature is an arbitrary byte string, rather than an
        !          1041: RFC 1421-encoded string.
        !          1042: 
        !          1043: signatureLen will not be greater than MAX_SIGNATURE_LEN.
        !          1044: 
        !          1045: Return value:      0     success
        !          1046:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1047:       RE_PRIVATE_KEY     privateKey cannot encrypt message digest
        !          1048: 
        !          1049: 
        !          1050: R_VerifyPEMSignature
        !          1051: 
        !          1052: int R_VerifyPEMSignature (
        !          1053:   unsigned char *content,                                /* content */ 
        !          1054:   unsigned int *contentLen,                    /* length of content */ 
        !          1055:   unsigned char *encodedContent,      /* (possibly) encoded content */
        !          1056:   unsigned int encodedContentLen,      /* length of encoded content */
        !          1057:   unsigned char *encodedSignature,             /* encoded signature */
        !          1058:   unsigned int encodedSignatureLen,  /* length of encoded signature */
        !          1059:   int recode,                                      /* recoding flag */
        !          1060:   int digestAlgorithm,                  /* message-digest algorithm */
        !          1061:   R_RSA_PUBLIC_KEY *publicKey            /* signer's RSA public key */
        !          1062: );
        !          1063: 
        !          1064: R_VerifyPEMSignature verifies a digital signature on a message. Its
        !          1065: operation is the inverse of R_SignPEMBlock. R_VerifyPEMSignature
        !          1066: operates on encodedSignature and encodedContent. If recode is
        !          1067: nonzero, it first decodes encodedContent according to RFC 1421, and
        !          1068: stores the result in content. If recode is zero, content is ignored.
        !          1069: 
        !          1070: If recode is nonzero, contentLen will not be greater than
        !          1071: DECODED_CONTENT_LEN(encodedContentLen).
        !          1072: 
        !          1073: Return value:      0     success
        !          1074:  RE_CONTENT_ENCODING     encodedContent has RFC 1421 encoding error
        !          1075: RE_SIGNATURE_ENCODING    encodedSignature has RFC 1421 encoding error
        !          1076:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1077:        RE_PUBLIC_KEY     publicKey cannot decrypt signature
        !          1078:         RE_SIGNATURE     signature on content is incorrect
        !          1079: 
        !          1080: 
        !          1081: R_VerifyBlockSignature
        !          1082: 
        !          1083: int R_VerifyBlockSignature (
        !          1084:   unsigned char *block,                                    /* block */
        !          1085:   unsigned int blockLen,                         /* length of block */
        !          1086:   unsigned char *signature,                            /* signature */  
        !          1087:   unsigned int signatureLen,                 /* length of signature */
        !          1088:   int digestAlgorithm,                  /* message-digest algorithm */
        !          1089:   R_RSA_PUBLIC_KEY *publicKey            /* signer's RSA public key */
        !          1090: );
        !          1091: 
        !          1092: R_VerifyBlockSignature verifies a digital signature on a block of
        !          1093: data such as a certificate. Its operation is similar to
        !          1094: R_VerifyPEMSignature, except that the block and signature are
        !          1095: arbitrary byte strings, rather than RFC 1421-encoded strings.
        !          1096: 
        !          1097: Return value:      0     success
        !          1098:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1099:        RE_PUBLIC_KEY     publicKey cannot decrypt signature
        !          1100:         RE_SIGNATURE     signature on block is incorrect
        !          1101: 
        !          1102: 
        !          1103: R_SealPEMBlock
        !          1104: 
        !          1105: int R_SealPEMBlock (
        !          1106:   unsigned char *encryptedContent,    /* encoded, encrypted content */
        !          1107:   unsigned int *encryptedContentLen,
        !          1108:                             /* length of encoded, encrypted content */
        !          1109:   unsigned char *encryptedKey,        /* encoded, encrypted DES key */  
        !          1110:   unsigned int *encryptedKeyLen,
        !          1111:                             /* length of encoded, encrypted DES key */  
        !          1112:   unsigned char *encryptedSignature,/* encoded, encrypted signature */
        !          1113:   unsigned int *encryptedSignatureLen,
        !          1114:                           /* length of encoded, encrypted signature */
        !          1115:   unsigned char iv[8],                 /* DES initialization vector */
        !          1116:   unsigned char *content,                                /* content */
        !          1117:   unsigned int contentLen,                     /* length of content */
        !          1118:   int digestAlgorithm,                  /* message-digest algorithm */
        !          1119:   R_RSA_PUBLIC_KEY *publicKey,        /* recipient's RSA public key */
        !          1120:   R_RSA_PRIVATE_KEY *privateKey,        /* signer's RSA private key */
        !          1121:   R_RANDOM_STRUCT *randomStruct                 /* random structure */
        !          1122: );
        !          1123: 
        !          1124: R_SealPEMBlock computes a digital signature on content then encrypts
        !          1125: the content and the signature. Specifically, R_SealPEMBlock performs
        !          1126: the following steps:
        !          1127: 
        !          1128:      1.   It digests content with digestAlgorithm, giving a message
        !          1129:           digest.
        !          1130: 
        !          1131:      2.   It encrypts the message digest with privateKey, giving a
        !          1132:           digital signature.
        !          1133: 
        !          1134:      3.   It generates a random DES key and initialization vector,
        !          1135:           storing the initialization vector in iv.
        !          1136: 
        !          1137:      4.   It encrypts content with the DES key and initialization vector
        !          1138:           in cipher-block chaining mode, and encodes the result in
        !          1139:           printable ASCII according to RFC 1421, storing the encoding
        !          1140:           in encryptedContent.
        !          1141: 
        !          1142:      5.   It encrypts the DES key with publicKey and encodes the
        !          1143:           result in printable ASCII, storing the encoding in
        !          1144:           encryptedKey.
        !          1145: 
        !          1146:      6.   It encrypts the digital signature with the DES key and
        !          1147:           initialization vector, and encodes the result in printable
        !          1148:           ASCII, storing the encoding in encryptedSignature.
        !          1149: 
        !          1150: encryptedContent will be an ASCII string, encoded according to RFC
        !          1151: 1421. (It will not contain any line delimiters; the application must
        !          1152: break the string into 64-character lines.) encryptedContentLen will
        !          1153: not be greater than ENCRYPTED_CONTENT_LEN(contentLen).
        !          1154: 
        !          1155: encryptedKey and encryptedSignature will be ASCII strings, encoded
        !          1156: according to RFC 1421. encryptedKeyLen will not be greater than
        !          1157: MAX_PEM_ENCRYPTED_KEY_LEN. encryptedSignatureLen will not be greater
        !          1158: than MAX_PEM_ENCRYPTED_SIGNATURE_LEN.
        !          1159: 
        !          1160: digestAlgorithm is the algorithm with which the message content is
        !          1161: digested, and must be one of the values listed in Appendix D.
        !          1162: 
        !          1163: randomStruct must have been seeded.
        !          1164: 
        !          1165: Return value:      0     success
        !          1166:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1167:       RE_PRIVATE_KEY     privateKey cannot encrypt message digest
        !          1168:        RE_PUBLIC_KEY     publicKey cannot encrypt DES key
        !          1169:       RE_NEED_RANDOM     randomStruct is not seeded
        !          1170: 
        !          1171: 
        !          1172: R_OpenPEMBlock
        !          1173: 
        !          1174: int R_OpenPEMBlock (
        !          1175:   unsigned char *content,                                /* content */
        !          1176:   unsigned int *contentLen,                    /* length of content */
        !          1177:   unsigned char *encryptedContent,    /* encoded, encrypted content */
        !          1178:   unsigned int encryptedContentLen,
        !          1179:                             /* length of encoded, encrypted content */
        !          1180:   unsigned char *encryptedKey,        /* encoded, encrypted DES key */  
        !          1181:   unsigned int encryptedKeyLen,
        !          1182:                             /* length of encoded, encrypted DES key */  
        !          1183:   unsigned char *encryptedSignature,/* encoded, encrypted signature */
        !          1184:   unsigned int encryptedSignatureLen,
        !          1185:                           /* length of encoded, encrypted signature */
        !          1186:   unsigned char iv[8],                 /* DES initialization vector */
        !          1187:   int digestAlgorithm,                  /* message-digest algorithm */
        !          1188:   R_RSA_PRIVATE_KEY *privateKey,     /* recipient's RSA private key */
        !          1189:   R_RSA_PUBLIC_KEY *publicKey            /* signer's RSA public key */
        !          1190: );
        !          1191: 
        !          1192: R_OpenPEMBlock decrypts an encrypted message and verifies a digital
        !          1193: signature. Its operation is the inverse of R_SealPEMBlock.
        !          1194: 
        !          1195: contentLen will not be greater than
        !          1196: DECRYPTED_CONTENT_LEN(encryptedContentLen).
        !          1197: 
        !          1198: Return value:       0    success
        !          1199:  RE_CONTENT_ENCODING     encryptedContent has RFC 1421 encoding error
        !          1200:      RE_KEY_ENCODING     encryptedKey has RFC 1421 encoding error
        !          1201: RE_SIGNATURE_ENCODING    encryptedSignature has RFC 1421 encoding
        !          1202:                            error
        !          1203:        RE_PUBLIC_KEY     publicKey cannot decrypt signature
        !          1204:       RE_PRIVATE_KEY     privateKey cannot decrypt encrypted key
        !          1205:               RE_KEY     recovered DES key cannot decrypt encrypted
        !          1206:                            content or encrypted signature
        !          1207:  RE_DIGEST_ALGORITHM     digestAlgorithm is invalid
        !          1208:         RE_SIGNATURE     signature on content is incorrect
        !          1209: 
        !          1210: 
        !          1211: R_DigestBlock
        !          1212: 
        !          1213: int R_DigestBlock (
        !          1214:   unsigned char *digest,                          /* message digest */
        !          1215:   unsigned int *digestLen,              /* length of message digest */ 
        !          1216:   unsigned char *content,                                /* content */
        !          1217:   unsigned int contentLen,                     /* length of content */
        !          1218:   int digestAlgorithm                   /* message-digest algorithm */
        !          1219: );
        !          1220: 
        !          1221: R_DigestBlock computes the message digest of content, storing the
        !          1222: resulting message digest in digest and its length in bytes in
        !          1223: digestLen.
        !          1224: 
        !          1225: digestAlgorithm is the algorithm with which the content is digested,
        !          1226: and must be one of the values in Appendix D.
        !          1227: 
        !          1228: digestLen will not be greater than MAX_DIGEST_LEN.
        !          1229: 
        !          1230: Return value:       0    success
        !          1231:   RE_DIGEST_ALGORITHM    digestAlgorithm is invalid
        !          1232: 
        !          1233: 
        !          1234: 8. RUN-TIME LIBRARY
        !          1235: 
        !          1236: RSAREF operates on memory blocks with three platform-specific library
        !          1237: procedures that are modeled after conventional C library functions:
        !          1238: 
        !          1239:              R_memcmp    compares two blocks of memory
        !          1240:              R_memcpy    copies a block of memory
        !          1241:              R_memset    sets a block of memory to a given value
        !          1242: 
        !          1243: These procedures can be found in the file 'r_stdlib.c'.
        !          1244: 
        !          1245: 
        !          1246: R_memcmp
        !          1247: 
        !          1248: int R_memcmp (
        !          1249:   POINTER firstBlock,                                /* first block */
        !          1250:   POINTER secondBlock,                              /* second block */
        !          1251:   unsigned int len                              /* length of blocks */
        !          1252: );
        !          1253: 
        !          1254: R_memcmp compares the first len bytes of firstBlock and secondBlock.
        !          1255: The value of len can be zero, in which case firstBlock and secondBlock
        !          1256: are undefined and R_memcmp returns 0. R_memcmp compares the blocks by
        !          1257: scanning the blocks from lowest address to highest until a difference
        !          1258: is found. The smaller-valued block is the one with the smaller-valued
        !          1259: byte at the point of difference. If no difference is found, the
        !          1260: blocks are equal.
        !          1261: 
        !          1262: Return value:     < 0    firstBlock is smaller
        !          1263:                   0      blocks are equal
        !          1264:                   > 0    firstBlock is larger
        !          1265: 
        !          1266: 
        !          1267: R_memcpy
        !          1268: 
        !          1269: void R_memcpy (
        !          1270:   POINTER output,                                   /* output block */
        !          1271:   POINTER input,                                     /* input block */
        !          1272:   unsigned int len                              /* length of blocks */
        !          1273: );
        !          1274: 
        !          1275: R_memcpy copies the first len bytes of input to output. The value of
        !          1276: len can be zero, in which output and input are undefined. The blocks
        !          1277: do not overlap.
        !          1278: 
        !          1279: No return value.
        !          1280: 
        !          1281: 
        !          1282: R_memset
        !          1283: 
        !          1284: void R_memset (
        !          1285:   POINTER output,                                   /* output block */
        !          1286:   int value,                                               /* value */
        !          1287:   unsigned int len                               /* length of block */
        !          1288: );
        !          1289: 
        !          1290: R_memset sets the first len bytes of output to value. The value of
        !          1291: len is zero, in which case output is undefined.
        !          1292: 
        !          1293: No return value.
        !          1294: 
        !          1295: 
        !          1296: APPENDIX A: RSAREF ERROR TYPES
        !          1297: 
        !          1298: This appendix lists RSAREF's error types.
        !          1299: 
        !          1300:              RE_DATA     other party's private value out of range
        !          1301: 
        !          1302:  RE_CONTENT_ENCODING     content, encrypted content, or encoded block
        !          1303:                            has RFC 1421 encoding error
        !          1304: 
        !          1305:  RE_DIGEST_ALGORITHM     message-digest algorithm is invalid
        !          1306: 
        !          1307:          RE_ENCODING     encoded block has RFC 1421 encoding error
        !          1308: 
        !          1309: RE_ENCRYPTION_ALGORITHM  encryption algorithm is invalid
        !          1310: 
        !          1311:               RE_KEY     recovered DES key cannot decrypt encrypted
        !          1312:                            content or encrypted signature
        !          1313: 
        !          1314:      RE_KEY_ENCODING     encrypted key has RFC 1421 encoding error
        !          1315: 
        !          1316:               RE_LEN     encrypted key length or signature length
        !          1317:                            out of range
        !          1318: 
        !          1319:       RE_MODULUS_LEN     modulus length out of range
        !          1320: 
        !          1321:       RE_NEED_RANDOM     random structure is not seeded
        !          1322: 
        !          1323:       RE_PRIVATE_KEY     private key cannot encrypt message digest,
        !          1324:                            or cannot decrypt encrypted key
        !          1325: 
        !          1326:        RE_PUBLIC_KEY     public key cannot encrypt data encryption
        !          1327:                            key, or cannot decrypt signature
        !          1328: 
        !          1329:         RE_SIGNATURE     signature on content or block is incorrect
        !          1330: 
        !          1331: RE_SIGNATURE_ENCODING    signature or encrypted signature has RFC 1421
        !          1332:                            encoding error
        !          1333: 
        !          1334: 
        !          1335: APPENDIX B: RSAREF TYPES
        !          1336: 
        !          1337: This appendix lists four RSAREF types: R_RSA_PUBLIC_KEY,
        !          1338: R_RSA_PRIVATE_KEY, R_RSA_PROTO_KEY, and R_DH_PARAMS.
        !          1339: 
        !          1340: 
        !          1341: R_RSA_PUBLIC_KEY
        !          1342: 
        !          1343: typedef struct {
        !          1344:   unsigned int bits;                   /* length in bits of modulus */
        !          1345:   unsigned char modulus[MAX_RSA_MODULUS_LEN];            /* modulus */
        !          1346:   unsigned char exponent[MAX_RSA_MODULUS_LEN];   /* public exponent */
        !          1347: } R_RSA_PUBLIC_KEY;
        !          1348: 
        !          1349: An R_RSA_PUBLIC_KEY value is a structure specifying an RSA public key.
        !          1350: There are three fields:
        !          1351: 
        !          1352:                 bits     length in bits of the modulus (not less than
        !          1353:                            MIN_RSA_MODULUS_BITS and not greater than
        !          1354:                            MAX_RSA_MODULUS_BITS)
        !          1355: 
        !          1356:              modulus     modulus n, represented as a
        !          1357:                            MAX_RSA_MODULUS_LEN-byte number, most
        !          1358:                            significant byte first, as many leading zero
        !          1359:                            bytes as necessary
        !          1360: 
        !          1361:             exponent     public exponent e, represented like modulus
        !          1362: 
        !          1363: 
        !          1364: R_RSA_PRIVATE_KEY
        !          1365: 
        !          1366: typedef struct {
        !          1367:   unsigned int bits;                   /* length in bits of modulus */
        !          1368:   unsigned char modulus[MAX_RSA_MODULUS_LEN];            /* modulus */
        !          1369:   unsigned char publicExponent[MAX_RSA_MODULUS_LEN];
        !          1370:                                                  /* public exponent */
        !          1371:   unsigned char exponent[MAX_RSA_MODULUS_LEN];  /* private exponent */
        !          1372:   unsigned char prime[2][MAX_RSA_PRIME_LEN];       /* prime factors */
        !          1373:   unsigned char primeExponent[2][MAX_RSA_PRIME_LEN];
        !          1374:                                                /* exponents for CRT */
        !          1375:   unsigned char coefficient[MAX_RSA_PRIME_LEN];  /* CRT coefficient */
        !          1376: } R_RSA_PRIVATE_KEY;
        !          1377: 
        !          1378: An R_RSA_PRIVATE_KEY value is a structure specifying an RSA private
        !          1379: key. There are seven fields:
        !          1380: 
        !          1381:                 bits     length in bits of the modulus (not less than
        !          1382:                            MIN_RSA_MODULUS_BITS and not greater than
        !          1383:                            MAX_RSA_MODULUS_BITS)
        !          1384: 
        !          1385:              modulus     modulus n, represented as a
        !          1386:                            MAX_RSA_MODULUS_LEN-byte number, most
        !          1387:                            significant byte first, as many leading zero
        !          1388:                            bytes as necessary
        !          1389: 
        !          1390:       publicExponent     public exponent e, represented like modulus
        !          1391: 
        !          1392:             exponent     private exponent d, represented like modulus
        !          1393: 
        !          1394:                prime     prime factors p and q of modulus, each
        !          1395:                            represented as MAX_RSA_PRIME_LEN-byte
        !          1396:                            numbers, most significant byte first, as
        !          1397:                            many leading zero bytes as necessary, where
        !          1398:                            p > q
        !          1399: 
        !          1400:       primeExponents     exponents (d mod p-1) and (d mod q-1) for
        !          1401:                            Chinese remainder theorem (CRT) operations,
        !          1402:                            each represented like prime factors
        !          1403: 
        !          1404:          coefficient     coefficient (q^{-1} mod p) for Chinese
        !          1405:                            remainder theorem operations, represented
        !          1406:                            like prime factors
        !          1407: 
        !          1408: 
        !          1409: R_RSA_PROTO_KEY
        !          1410: 
        !          1411: typedef struct {
        !          1412:   unsigned int bits;                   /* length in bits of modulus */
        !          1413:   int useFermat4;                /* public exponent (1 = F4, 0 = 3) */
        !          1414: } R_RSA_PROTO_KEY;
        !          1415: 
        !          1416: An R_RSA_PROTO_KEY value is a structure specifying the length in bits
        !          1417: of the RSA modulus and the public exponent for key-pair generation.
        !          1418: There are two fields:
        !          1419: 
        !          1420:                 bits     length in bits of the modulus (not less than
        !          1421:                            MIN_RSA_MODULUS_BITS and not greater than
        !          1422:                            MAX_RSA_MODULUS_BITS)
        !          1423: 
        !          1424:           useFermat4     a flag specifying the public exponent. If
        !          1425:                            nonzero, it specifies F4 (65537); if 0, F0
        !          1426:                            (3)
        !          1427: 
        !          1428: 
        !          1429: R_DH_PARAMS
        !          1430: 
        !          1431: typedef struct {
        !          1432:   unsigned char *prime;                                    /* prime */
        !          1433:   unsigned int primeLen;                         /* length of prime */
        !          1434:   unsigned char *generator;                            /* generator */
        !          1435:   unsigned int generatorLen;                 /* length of generator */
        !          1436: } R_DH_PARAMS;
        !          1437: 
        !          1438: An R_DH_PARAMS value is a structure specifying Diffie-Hellman
        !          1439: parameters. There are four fields:
        !          1440: 
        !          1441:                prime     prime p, represented as a primeLen-byte
        !          1442:                            number, most significant byte first, as
        !          1443:                            many leading zero bytes as necessary
        !          1444: 
        !          1445:             primeLen     length in bytes of the prime
        !          1446: 
        !          1447:            generator     generator g, represented like prime
        !          1448: 
        !          1449:         generatorLen     length in bytes of the generator
        !          1450: 
        !          1451: 
        !          1452: APPENDIX C: PLATFORM-SPECIFIC TYPES AND CONSTANTS
        !          1453: 
        !          1454: This appendix lists three platform-specific types and one #define'd
        !          1455: constant.
        !          1456: 
        !          1457: 
        !          1458: TYPES
        !          1459: 
        !          1460: RSAREF requires three platform-specific types: POINTER, UINT2, and
        !          1461: UINT4. These are defined in the file 'global.h'.
        !          1462: 
        !          1463: 
        !          1464: POINTER
        !          1465: 
        !          1466: A POINTER value is a generic pointer to memory to which any other
        !          1467: pointer can be cast.
        !          1468: 
        !          1469: Example:
        !          1470: 
        !          1471:     typedef unsigned char *POINTER;
        !          1472: 
        !          1473: 
        !          1474: UINT2
        !          1475: 
        !          1476: A UINT2 value is a 16-bit unsigned integer.
        !          1477: 
        !          1478: Example:
        !          1479: 
        !          1480:     typedef unsigned short int UINT2;
        !          1481: 
        !          1482: 
        !          1483: UINT4
        !          1484: 
        !          1485: A UINT4 value is a 32-bit unsigned integer.
        !          1486: 
        !          1487: Example:
        !          1488: 
        !          1489:     typedef unsigned long int UINT4;
        !          1490: 
        !          1491: 
        !          1492: #DEFINE'D CONSTANTS
        !          1493: 
        !          1494: RSAREF requires one #define'd constant: PROTOTYPES. This is defined
        !          1495: in the 'makefile' on the C compiler command line.
        !          1496: 
        !          1497: PROTOTYPES indicates the form that C function declarations are to
        !          1498: take. If PROTOTYPES is nonzero, declarations take the form
        !          1499: 
        !          1500:     type function (type, ..., type);
        !          1501: 
        !          1502: Otherwise declarations take the form
        !          1503: 
        !          1504:     type function ();
        !          1505: 
        !          1506: 
        !          1507: APPENDIX D: ENCRYPTION ALGORITHMS AND IDENTIFIERS
        !          1508: 
        !          1509: This appendix lists message-digest and data encryption algorithms and
        !          1510: their identifiers.
        !          1511: 
        !          1512: 
        !          1513: D.1 Message-digest algorithms
        !          1514: 
        !          1515: RSAREF supports two message-digest algorithms, listed here with their
        !          1516: integer identifiers:
        !          1517: 
        !          1518:               DA_MD2     MD2 message-digest algorithm [3]
        !          1519: 
        !          1520:               DA_MD5     MD5 message-digest algorithm [4]
        !          1521: 
        !          1522: 
        !          1523: D.2 Data encryption algorithms
        !          1524: 
        !          1525: RSAREF supports four data encryption algorithms, listed here with
        !          1526: their integer identifiers:
        !          1527: 
        !          1528:           EA_DES_CBC     Data Encryption Standard [5] in cipher-block
        !          1529:                            chaining (CBC) mode [6]
        !          1530: 
        !          1531:          EA_DESX_CBC     RSA Data Security's DESX enhancement of DES,
        !          1532:                            in CBC mode (this algorithm exclusive-ors
        !          1533:                            with the previous ciphertext block,
        !          1534:                            exclusive-ors with a secret value, encrypts
        !          1535:                            with DES, then exclusive-ors with a second
        !          1536:                            secret value)
        !          1537: 
        !          1538:       EA_DES_EDE3_CBC    Three-key triple-DES in CBC mode (this
        !          1539:                            algorithm exclusive-ORs with the previous
        !          1540:                            ciphertext block, encrypts with one DES
        !          1541:                            key, decrypts with a second DES key, then
        !          1542:                            encrypts with a third DES key)
        !          1543: 
        !          1544:       EA_DES_EDE2_CBC    Two-key triple-DES in CBC mode (like three-
        !          1545:                            key, except that the first and third DES
        !          1546:                            keys are the same)
        !          1547: 
        !          1548: All four algorithms have a block size of eight bytes, and hence an
        !          1549: eight-byte initialization vector. All employ the padding rules
        !          1550: described in RFC 1423 [11].
        !          1551: 
        !          1552: 
        !          1553: REFERENCES
        !          1554: 
        !          1555: [1]  R.L. Rivest, A. Shamir, and L. Adleman. A method for obtaining
        !          1556:      digital signatures and public-key cryptosystems. Communications
        !          1557:      of the ACM, 21(2):120-126, February 1978.
        !          1558: 
        !          1559: [2]  RSA Laboratories. PKCS #1: RSA Encryption Standard. Version 1.5,
        !          1560:      November 1993. (PKCS documents are available via electronic mail
        !          1561:      to <[email protected]>.)
        !          1562: 
        !          1563: [3]  B. Kaliski. RFC 1319: The MD2 Message-Digest Algorithm. April
        !          1564:      1992.
        !          1565: 
        !          1566: [4]  R. Rivest. RFC 1321: The MD5 Message-Digest Algorithm. April
        !          1567:      1992.
        !          1568: 
        !          1569: [5]  National Bureau of Standards. FIPS Publication 46-1: Data
        !          1570:      Encryption Standard. January 1988.
        !          1571: 
        !          1572: [6]  National Bureau of Standards. FIPS Publication 81: DES Modes of
        !          1573:      Operation. December 1980.
        !          1574: 
        !          1575: [7]  W. Diffie and M.E. Hellman. New directions in cryptography. IEEE
        !          1576:      Transactions on Information Theory, IT-22:644-654, 1976.
        !          1577: 
        !          1578: [8]  RSA Laboratories. PKCS #3: Diffie-Hellman Key-Agreement Standard.
        !          1579:      Version 1.4, November 1993.
        !          1580: 
        !          1581: [9]  J. Linn. RFC 1421: Privacy Enhancement for Internet Electronic
        !          1582:      Mail: Part I: Message Encryption and Authentication Procedures.
        !          1583:      February 1993.
        !          1584: 
        !          1585: [10] S. Kent. RFC 1422: Privacy Enhancement for Internet Electronic
        !          1586:      Mail: Part II: Certificate-Based Key Management. February 1993.
        !          1587: 
        !          1588: [11] D. Balenson. RFC 1423: Privacy Enhancement for Internet
        !          1589:      Electronic Mail: Part III: Algorithms, Modes, and Identifiers.
        !          1590:      February 1993.
        !          1591: 
        !          1592: [12] B. Kaliski. RFC 1424: Privacy Enhancement for Internet Electronic
        !          1593:      Mail: Part IV: Key Certification and Related Services. February
        !          1594:      1993.
        !          1595: 
        !          1596: [13] RSA Laboratories. PKCS #7: Cryptographic Message Syntax Standard.
        !          1597:      Version 1.5, November 1993.
        !          1598: 
        !          1599: [14] RSA Laboratories. PKCS #10: Certification Request Syntax
        !          1600:      Standard. Version 1.0, November 1993.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.