CryptoSys PKI Toolkit Manual

RSA_DecodeMsg

RSA_DecodeMsg decodes an EME or EMSA encoded message block according to PKCS#1 (EME = Encoding Method for Encryption, EMSA = Encoding Method for Signature with Appendix).

VB6/VBA Syntax

Public Declare Function RSA_DecodeMsg Lib "diCrPKI.dll" (ByRef abOutput As Byte, ByVal nOutChars As Long, ByRef abInput As Byte, ByVal nInputLen As Long, ByVal nOptions As Long) As Long

nRet = RSA_DecodeMsg(abOutput(0), nOutputLen, abInput(0), nInputLen, nOptions)

Parameters

abOutput
[out] Byte array to receive the decoded output.
nOutputLen
[in] Long specifying the maximum length of the output array.
abInput
[in] Byte array containing the data to be decoded.
nInputLen
[in] Long specifying the number of bytes in the input.
nOptions
[in] Long option flags. Include one of the following:-
PKI_EME_PKCSV1_5 (0) to decode an 'Encoded Message for Encryption' block using PKCS#1 v1.5 method (default)
PKI_EME_OAEP to decode an 'Encoded Message for Encryption' block using OAEP method
PKI_EMSIG_PKCSV1_5 to decode an `Encoded Message for Signature' block using PKCS#1 v1.5 method
and, if you have selected PKI_EMSIG_PKCSV1_5, then you can add:
PKI_EMSIG_DIGINFO to decode an 'Encoded Message for Signature' block and output the whole DigestInfo data instead of just the message

Alternatively, ignore all the above and use the specialist option
PKI_EMSIG_ISO9796 to use the ISO9796-1 encoding for a signature. See AUTACK messages and ISO/IEC 9796-1 signatures for more details.

C/C++ Syntax

long _stdcall RSA_DecodeMsg(unsigned char *abOutput, long nOutputLen, const unsigned char *abInput, long nInputLen, long nOptions);

Returns (VB6/C)

Long: If successful, the return value is the number of bytes required to store the full output data. If an error occurs, it returns a negative error code.

.NET Equivalent

Rsa.DecodeMsgForEncryption Method
Rsa.DecodeDigestForSignature Method (Byte[], Boolean)

Remarks

This function recovers the relevant data from an encoded message block according to the algorithms in PKCS#1.

Decoding an EME Block

The objective is to recover the original message data which is encoded in the block. Use either

nOptions = PKI_EME_PKCSV1_5

or

nOptions = PKI_EME_OAEP

You need to know which algorithm was used to create the block in the first place.

Decoding an EMSA Block

The objective is to verify that the encoded message digest hash matches the message digest hash of the original message.

Note: it is much simpler to use the RSA_EncodeMsg function on the original message and then compare the result of that with the input block you have here. See Raw RSA Techniques. The options here are included for advanced users.

There are two choices when decoding an EMSA block:

  1. Extract the message digest bytes. Set
    nOptions = PKI_EMSIG_PKCSV1_5
  2. Extract the whole DigestInfo bytes. Set
    nOptions = PKI_EMSIG_PKCSV1_5 + PKI_EMSIG_DIGINFO
    You might use this if you come across a hash algorithm that is not supported by this Toolkit. Use this option to recover the entire DigestInfo and then inspect the bytes to work out what it is, using your knowledge of DER encoding.

Remember that the result of a decode operation for a signature is to recover the hash digest of the original message. The next step is to generate an independent hash digest of the message itself and compare that to the digest recovered here. If they match, the signature is verified. Alternatively, just generate another EMSA block from the message and compare that directly.

For full details of the background and mechanics, please refer to the original specification document [PKCS1]. Note that the EMSA-PSS signature scheme, introduced in version PKCS#1 v2.1, is not supported in this application because it is subject to a patent application and there are (currently) no known attacks on the default EMSA algorithm.

Example

    Dim abData() As Byte
    Dim abBlock() As Byte
    Dim abDigest() As Byte
    Dim abDigInfo() As Byte
    Dim nDataLen As Long
    Dim nBlockLen As Long
    Dim nLen As Long
    Dim nRet As Long
    Dim nOptions As Long
    
    ' 0. Create an encoded test block ready for for signing
    abData = StrConv("abc", vbFromUnicode)
    nDataLen = UBound(abData) - LBound(abData) + 1
    nBlockLen = 64
    ReDim abBlock(nBlockLen - 1)
    nRet = RSA_EncodeMsg(abBlock(0), nBlockLen, abData(0), nDataLen, PKI_EMSIG_PKCSV1_5)
    Debug.Print "BLOCK   =" & cnvHexStrFromBytes(abBlock)
    
    ' 1. Extract the message digest =SHA1("abc")
    nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, PKI_EMSIG_PKCSV1_5)
    If nLen < 0 Then MsgBox "Decryption Error": Exit Function
    Debug.Print "Message digest is " & nLen & " bytes long"
    ReDim abDigest(nLen - 1)
    nLen = RSA_DecodeMsg(abDigest(0), nLen, abBlock(0), nBlockLen, PKI_EMSIG_PKCSV1_5)
    Debug.Print "HASH    =" & cnvHexStrFromBytes(abDigest)
    
     ' 2. Extract the full DigestInfo data
    nOptions = PKI_EMSIG_PKCSV1_5 + PKI_EMSIG_DIGINFO
    nLen = RSA_DecodeMsg(0, 0, abBlock(0), nBlockLen, nOptions)
    If nLen < 0 Then MsgBox "Decryption Error": Exit Function
    Debug.Print "DigestInfo is " & nLen & " bytes long"
    ReDim abDigest(nLen - 1)
    nLen = RSA_DecodeMsg(abDigest(0), nLen, abBlock(0), nBlockLen, nOptions)
    Debug.Print "DIGINFO=" & cnvHexStrFromBytes(abDigest)

This should produce results like:

BLOCK  =0001FFFFFF...C26C9CD0D89D
Message digest is 20 bytes long
HASH   =A9993E364706816ABA3E25717850C26C9CD0D89D
DigestInfo is 35 bytes long
DIGINFO=3021300906052B0E03021A05000414A9993E364706816ABA3E25717850C26C9CD0D89D

See Also

RSA_EncodeMsg RSA_RawPublic RSA_RawPrivate Raw RSA Techniques

[Contents] [Index]

[HOME]   [NEXT: RSA_EncodeMsg...]

Copyright © 2004-9 D.I. Management Services Pty Ltd. All rights reserved.