| RIM Crypto API: Adding Encoding Schemes to the API |
Encoding rules determine how cryptographic data such as keys and signatures, along with their associated parameters, are transmitted from one client to another. As the number of available algorithms increases, encoding becomes especially important to avoid confusion. Significant support for key and signature encoding is present in the Crypto API, but like anything else, the developer may need to add support for some new encoding format.
How Encoding Works in the API
Before attempting to add a new encoding algorithm to the Crypto API, it is necessary to examine how encoding is dealt with in the API. As an example, consider the following code for encoding a PKCS8 EC private key:
// Create the crypto system and a private key
ECCryptoSystem system = new ECCryptoSystem();
ECKeyPair keyPair = new ECKeyPair( system );
ECPrivateKey key = (ECPrivateKey)keyPair.getPrivateKey();
// Now encode the key
EncodedKey encodedKey = PrivateKeyEncoder.encode( key, "PKCS8" );
byte[] encodedKeyData = encodedKey.getEncodedKey();
If the key is subsequently decoded, all the necessary information can be extracted from the encoded key, and the programmer need only pass in the encoded key:
ECPrivateKey decodedKey = (ECPrivateKey)PrivateKeyDecoder.decode( encodedKeyData, "PKCS8" );
This code is representative of the encoding (and decoding) process in general. Encoding a
signature or public key is virtually identical, except that SignatureEncoder.encode()
or PublicKeyEncoder.encode() would be called. If the developer wanted to
use an X509 encoding scheme instead of PKCS8 in the above example, he or she could have
simply passed in the string "X509" with the call to encode().
The simple calls to encode() and decode() are all that are necessary
to use the existing encoding schemes. However, the situation is more complex behind the scenes.
The API must know which classes and methods to call based on the encoding scheme and algorithm
in use.
Adding Private Key Encoding Algorithms
In the case of the above encoding example, the correct class was determined and the appropriate
method was called behind the scenes, transparent to the developer. PKCS8_EC_PrivateKeyEncoder
is the class that handles encoding for EC private keys under the PKCS8 encoding scheme. It has an
encodeKey() method which is responsible for performing the actual encoding operation on the
key data. To add a new encoding algorithm, the developer must simply extend PrivateKeyEncoder,
override the appropriate methods (summarized later in this lesson), and register the encoder with the
framework by calling PrivateKeyEncoder.add().
To decode the now-encoded key, the process is a bit more complex. The key decoder is simply passed a blob
of data containing a private key. All that is known is the encoding scheme used; the key could be of any
type supported. Therefore, a two-layer model was chosen for decoding operations. When
PrivateKeyDecoder.decode() is called, it checks the encoded key to determine its specific type
(through information stored with the key), and then passes the key on to the specific private key decoder,
which can perform the actual decoding operation.
To add a decoder, two classes must be present for the
framework: a general decoder class for the scheme (the first layer, which may already exist in the API or
may be provided by the developer), and a decoder class for the specific key type (provided by the developer).
So, if the scheme is one already supported by the API (ie PKCS8, X509, WTLS), the developer must simply create
a class extending the existing base decoder class (such as PKCS8_PrivateKeyDeocder)
that provides decoding support for the specific key type desired.
Similar to the encoders, decodeKey() must be implemented, and the class must be registered with
the framework with a call to add().
If the encoding scheme is not supported by the API, then the developer must create
both a base class for the scheme as well as classes for the specific key types that are to be supported. These
classes can be registered with the framework through the PrivateKeyDecoder.add() method.
Steps for Adding New Encoding Algorithms
The above example was for a private key encoder and decoder, but the steps for public key and signature encoders and decoders are very similar. The following tables summarize the steps involved in adding new encoding algorithms:
Encoders
| Type | Base Class | Encoder Class | Steps Required to Add |
| Signature encoder | SignatureEncoder |
XXXX_SignatureEncoder
Extends: |
Create a class extending SignatureEncoder.
Implement methods: Call |
| Public key encoder | PublicKeyEncoder |
XXXX_PublicKeyEncoder
Extends: |
Create a class extending PublicKeyEncoder.
Implement methods: Call |
| Private key encoder | PrivateKeyEncoder |
XXXX_PrivateKeyEncoder
Extends: |
Create a class extending PrivateKeyEncoder.
Implement methods: Call |
| Symmetric key encoder | SymmetricKeyEncoder |
XXXX_SymmetricKeyEncoder
Extends: |
Create a class extending SymmetricKeyEncoder.
Implement methods: Call |
Decoders
| Type | Base Class | Decoder Class | Steps Required to Add |
| Signature decoder |
X509_SignatureDecoderWTLS_SignatureDecoder- OR - Some class provided by the developer that extends SignatureDecoder
|
XXXX_SignatureDecoder
Extends: One of the base classes from the previous column |
If this is an unsupported encoding scheme, create a base class extending
SignatureDecoder that all specific decoders will subclass. Otherwise,
use an existing base class.Create a class extending the chosen base class. Implement methods (in base class and subclass): Call |
| Public key decoder |
X509_PublicKeyDecoderWTLS_PublicKeyDecoder- OR - Some class provided by the developer that extends PublicKeyDecoder
|
XXXX_PublicKeyDecoder
Extends: One of the base classes from the previous column |
If this is an unsupported encoding scheme, create a base class extending
PublicKeyDecoder that all specific decoders will subclass. Otherwise,
use an existing base class.Create a class extending the chosen base class. Implement methods (in base class and subclass): Call |
| Private key decoder |
PKCS8_PrivateKeyDecoder- OR - Some class provided by the developer that extends PrivateKeyDecoder
|
XXXX_PrivateKeyDecoder
Extends: One of the base classes from the previous column |
If this is an unsupported encoding scheme, create a base class extending
PrivateKeyDecoder that all specific decoders will subclass. Otherwise,
use an existing base class.Create a class extending the chosen base class. Implement methods (in base class and subclass): Call |
| Symmetric key decoder |
PKCS8_SymmetricKeyDecoder- OR - Some class provided by the developer that extends SymmetricKeyDecoder
|
XXXX_SymmetricKeyDecoder
Extends: One of the base classes from the previous column |
If this is an unsupported encoding scheme, create a base class extending
SymmetricKeyDecoder that all specific decoders will subclass. Otherwise,
use an existing base class.Create a class extending the chosen base class. Implement methods (in base class and subclass): Call |