Key Manager
The Key Manager (KM) provides JavaScript applications with key management and cryptographic functionality. It makes this available on the device's public bus via a number of API calls. The Key Manager implements a key store , allowing apps a place to safely keep keys where they are readily available for cryptographic operations.

The Key Manager is designed to do the following:
-
Provide apps and services easy access to cryptographic functions they need to perform local tasks safely, comply with standards, and interact with external services.
-
Protect user secrets (keys, passwords, etc.) in the event of loss or theft. Even if the device is in Developer Mode, possession alone should not provide access to secrets.
-
Protect application secrets (keys, tokens, etc.) from disclosure to the user or other applications.
-
Provide apps and services access, via a flexible and easy-to-use interface, to commonly used encryption algorithms such as AES, 3DES, and HMAC, and digest functions such as SHA-1.
Keys are stored encrypted in a database. They have both an app name (i.e., "com.someone.appname"
) and a key name. The latter is not necessarily unique—two different apps can both have a key with the same name. However, the Key Manager service obtains the app name from the protocol, making it almost impossible for apps to use the same keys.
An app can use the KM service to store or generate a key while specifying its encryption algorithm type, length, and an option to hide the key and never return it to the application, though it remains available for cryptographic operations.
In this section:
Supported Key Types
In cryptography, a key is a piece of information (a parameter) that determines the functional output of a cryptographic algorithm or cipher. Without a key, the algorithm would have no result. In encryption, a key specifies the particular transformation of plaintext (unencrypted text) into ciphertext (encrypted text), or vice-versa during decryption. Keys are also used in other cryptographic algorithms, such as digital signature schemes and message authentication codes.
Key Manager supports the following key encryption algorithm types:
-
AES—Advanced Encryption Standard. AES-128, AES-192, and AES-256 are supported.
-
3DES (3 key outer CBC)—The size includes the padding.
-
HMAC — SHA1 —Hash-based Message Authentication Code - Secure Hash Algorithm-1 . Any size from 16 bytes up is supported.
-
BLOB—For storing any type of data, up to 4k bytes.
-
ASCIIBLOB—An ascii (non-base64 encoded) BLOB. The data must be in valid JSON format with no unescaped JSON formatting characters.
Supported Block Cipher Modes
A block cipher is a type of symmetric-key encryption algorithm that transforms a fixed-length block of plaintext data into a block of ciphertext data of the same length. This transformation takes place with the aid of a user-provided secret key. Decryption is performed by applying the reverse transformation to the ciphertext block using the same secret key. The fixed length is called the block size, and for many block ciphers, the block size is 64 bits or 128 bits.
AES and 3DES are the supported block ciphers.
Key Manager supports the following block cipher modes:
- CBC—Cipher Block Chaining.
- ECB—Electronic CodeBook.
- CFB—Cipher FeedBack Mode.
Supported Block Cipher Padding Modes
Because a block cipher works on units of a fixed size, but messages come in a variety of lengths, some modes (mainly CBC) require that the final block be padded before encryption.
Key Manager supports the following block cipher padding modes:
- None—Data must be a multiple of the block size.
- PKCS1—Public Key Cryptography Standards #1.
Methods
You can asynchronously call Key Manager methods through the serviceRequest
function which takes 2 parameters:
- The Key Manager URI (Uniform Resource Identifier).
- A JSON (JavaScript Object Notation) object containing parameters, callback functions, and other data.
Depending on outcome, the API returns a JSON result to either the success or failure callback function. These functions can then parse the result. Your app needs to take into account the call's asynchronous nature (results may be delayed) and not block user interaction while awaiting results.
About JSON
For more information on calling services such as Key Manager, see the Services Overview.
JSON is a lightweight data-interchange text format based on a subset of the JavaScript programming language that is easy for humans to read and write and for machines to parse and generate. Like XML, JSON contains name/value pair collections and ordered list of values (i.e., arrays).
For more information on JSON, see the following websites:
- JSON objects, values and format—http://www.json.org/
- JSON schemas—http://tools.ietf.org/html/draft-zyp-json-schema-02
A primer on how JSON data objects are formatted is beyond the scope of this document—consult the two links above for more information. However, in brief:
- Curly brackets ('{', '}') are used to enclose objects.
- Angle brackets ('[', ']') are used to enclose arrays.
- Colons (':') are used as delimiters in name/value pairs.
- Quotes (") are used for string values. Numeric values are not quoted.
Data Formatting
Since JSON objects are composed and formatted with ascii (UTF-8) text, data to and from the Key Manager service needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. This includes key data, data to be encrypted or decrypted, and IVs (Initialization Vectors). The webOS JavaScript foundation libraries provide the following base64 encoding and decoding functions: TBD
Key Manager Public Methods
- crypt—Encrypts or decrypts data.
- export—Wraps a key using a specified wrapping key.
- fetchKey—Returns key metadata and key data.
- generate—Generates a key.
- import—Takes a wrapped key and imports it.
- keyInfo—Returns key metadata but not the key data.
- remove—Deletes a key from the database.
- store—Stores a key in the database.
crypt
You can use this API to encrypt or decrypt data. The key encryption algorithm specified (AES, 3DES, or HMACSHA1) must be the same as the one used to create the key.
Key data needs to be base64 encoded. Since JSON objects are composed and formatted with ascii (UTF-8) text, data needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. The webOS JavaScript foundation libraries provide the following base64 encoding/decoding functions: TBD
Schema
{ "keyname" : string, "algorithm" : string, "pad" : string, "mode" : string, "iv" : string, "decrypt" : boolean, "data" : string }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Key name. |
algorithm | Yes | string |
Possible values: "AES", "3DES", or "HMACSHA1" .
|
pad | No | string |
Possible values: "PKCS1" , or "none" . Required for block ciphers.
|
mode | No | string |
Possible values: "CBC", "CFB", "ECB", or "none" . This is only appropriate for block ciphers. none is not valid for block ciphers.
|
iv | No | string | Initialization Vector—a block of bits that is required to allow a stream cipher or a block cipher to to produce a unique stream independent from other streams produced by the same encryption key without having to go through a re-keying process. Only required for CBC and CFB modes. 16 bytes for AES, 8 bytes for 3DES. |
decrypt | Yes | boolean |
false to encrypt, true to decrypt.
|
data | Yes | string | Data to encrypt or decrypt. |
Returns
{ "returnValue" : boolean, "errorText" : string, | "data" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure)
|
errorText | No | string | Error message returned on failure. |
data | No | string | Encrypted data. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "crypt", parameters: { "keyname" : "myKey", "algorithm" : "AES", "decrypt" : false, "data" : "Here is my secret, secret credit card number: 3456-8720-8735=0678" }, onSuccess: function(e){ Mojo.Log.info("Crypt success, data="+e.data); }, onFailure: function(e){ Mojo.Log.info("Crypt failure, err="+e.errorText); } });
export
Wraps a key using a specified wrapping key. Both keys must belong to the same owner. A key can not wrap itself.
Schema
{ "keyname" : string, "wrappingkeyname": string }
Parameters
Argument | Type | Description |
---|---|---|
keyname | string | Key name. |
wrappingkeyname | string | Wrapping key name. |
Returns
{ "returnValue" : boolean, "errorText" : string, | "wrappedkey" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure)
|
errorText | No | string | Error message returned on failure. |
wrappedkey | No | string | Wrapped key returned on success. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "export", parameters: { "keyname": "MyKey", "wrappingkeyname": "MyWrappingKey" }, onSuccess: function(e) {Mojo.Log.info("KeyManager: export success="+JSON.stringify(e));}, onFailure: function(e) {Mojo.Log.info("KeyManager: export failure="+JSON.stringify(e));} });
fetchKey
Returns key metadata and key data. Key data is returned if the key had been originally stored or generated with nohide = true
. Otherwise, the call fails and a "key is not exportable" error message is returned.
Schema
{ "keyname" : string }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Key name. |
Returns
{ "returnValue" : boolean, "errorText" : string, | "keyname" : string, "type" : string, "keydata" : string "nohide" : boolean }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message returned on failure. |
keyname | No | string | Key name. Returned on success. |
type | No | string |
Key type. One of the following—"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB" . Returned on success.
|
keydata | No | string |
Optional key data string. Returned if nohide is true . Returned on success.
|
nohide | No | boolean |
If true , it means key data can be returned with this call. Returned on success.
|
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "fetchKey", parameters: { "keyname" :"MyKey" }, onSuccess: function(e){ var MyKeyB64 = Base64.decode(e.keydata); Mojo.Log.info("KeyManager: fetchKey Success: keydata= "+MyKeyB64+ ", keyname="+e.keyname); }, onFailure: function(e){ Mojo.Log.info("fetchKey Failure, err="+e.errorText); } });
generate
Generates a key with the name specified. If nohide = true
, the key data can be accessed with fetchKey
.
Types and their size requirements:
- AES—16 (default), 24 or 32 bytes. These sizes correspond to AES 128, 192 or 256 bit.
- 3DES—24 bytes.
- HMACSHA1—16 bytes or up.
- BLOB—Up to 4096 bytes. The BLOB type is used for safely storing data of any kind.
- ASCIIBLOB—Same as BLOB but for storing ascii, JSON formatted text that is not base64 encoded.
Schema
{ "keyname": string, "size" : integer, "type" : string, "nohide" : boolean }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Name of key to generate. |
size | Yes | integer | Key size in bytes. |
type | Yes | string |
Key type. Must be one of the following—"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB" .
|
nohide | No | boolean |
If false (default), the key data can not be exported with fetchKey .
|
Returns
{ "returnValue" : boolean, "errorText" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message returned on failure. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "generate", parameters: { "keyname" : "MyGenKey", "size" : 16, "type" : "HMACSHA1", "nohide" : true }, onSuccess: function(e){ Mojo.Log.info("KeyManager: Generate MyGenKey success, e="+JSON.stringify(e)); }, onFailure: function(e){ Mojo.Log.info("KeyManager: Generate MyGenKey failure, e="+JSON.stringify(e)); } });
import
Import takes a wrapped key and imports it. If the wrapping key is not present, the key is not installed and an error is returned. If successful, the unwrapped key's name is returned. A wrapped key can not replace an existing key with the same owner and name.
Schema
{ "wrappedKey": string }
Parameters
Argument | Type | Description |
---|---|---|
wrappedKey | string | Wrapped key. |
Returns
{ "returnValue" : boolean, "errorText" : string, | "keyname" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message returned on failure. Returned on success. |
keyname | No | string | Key name. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "import", parameters: { "wrappedKey": "MyWrappedKey" }, onSuccess: function(e){ Mojo.Log.info("Import success, e="+JSON.stringify(e)); }, onFailure: function(e){ Mojo.Log.info("Import failure, e="+JSON.stringify(e)); } });
keyInfo
Returns the key's metadata but not the key data.
Schema
{ "keyname" : string }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Key name |
Returns
{ "returnValue" : boolean, "errorText" : string, | "keyname" : string, "type" : string, "nohide" : boolean, "backup" : boolean, "noexport" : boolean, "cloud" : boolean, "unwrap_only" : boolean, "shared" : boolean }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message returned on failure. |
keyname | No | string | Key name. Returned on success. |
type | No | string |
One of the following—"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB" . Returned on success.
|
nohide | No | boolean |
Indicates if key data is accessible via fetchKey (true ), or can only be used for operations (false ). Returned on success.
|
backup | No | boolean | Is this key backed up in the cloud with the device backup? Returned on success. |
noexport | No | boolean | Key can be exported flag. Returned on success. |
cloud | No | boolean | Is this key stored in the cloud and used for backups? Returned on success. |
unwrap_only | No | boolean |
If true , key can only be used to unwrap wrapped keys and no other operation. Returned on success.
|
shared | No | boolean | Can other apps access the key flag. Returned on success. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "keyInfo", parameters: { "keyname" :"MyKey" }, onSuccess: function(e){ Mojo.Log.info("keyInfo Success: type= "+e.type); }, onFailure: function(e){ Mojo.Log.info("keyInfo Failure err="+JSON.stringify(e)); } });
remove
Given a key name, removes a key from the key store.
Schema
{ "keyname" : string }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Key name. |
Returns
{ "returnValue" : boolean, "errorText" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message on failure. |
Example
this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "remove", parameters: { "keyname" : "MyKey4" }, onSuccess: function(e){ Mojo.Log.info("Remove key success"); }, onFailure: function(e){ Mojo.Log.info("Remove key failure, err="+JSON.stringify(e)); } });
store
Stores a key in the database given a key name, data, key encryption algorithm type, and other optional parameters.
Key data needs to be base64 encoded unless its type
is ASCIIBLOB
. Since JSON objects are composed and formatted with ascii (UTF-8) text, data needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. The webOS JavaScript foundation libraries provide the following base64 encoding/decoding functions: TBD
Type
must be one of the supported key types—AES, 3DES, HMACSHA1, BLOB, or ASCIIBLOB.
BLOB
is not actually a key type, but can be used to safely store data (up to 4096 bytes) of any kind. ASCIIBLOB
is the same as BLOB
, but for storing ascii, JSON formatted text.
If nohide
is set to false
(default), the key data can not be exported with fetchKey. BLOB
types should not have nohide
set, as that makes them useless.
The backup
flag (keys backed up in the cloud with the device backup) is false
by default.
The cloud
flag indicates a key which is stored in the cloud and is a special key for backups. If true
, The type should be ASCIIBLOB
and the keydata contains the backup-specific part of the URL for fetching the key.
Schema
{ "keyname" : string, "keydata" : string, "type" : string, "nohide" : boolean, "backup" : boolean, "cloud" : boolean }
Parameters
Argument | Required | Type | Description |
---|---|---|---|
keyname | Yes | string | Key name. |
keydata | Yes | string | Key data. |
type | Yes | string | Key algroithm encryption type. Must be one of the following—AES, 3DES, HMACSHA1, BLOB, or ASCIIBLOB. 3DES keys must be properly formed with DES parity bits and weak key checking already done. |
nohide | No | boolean |
If false (default), the key data can not be exported with fetchKey .
|
backup | No | boolean |
If true , this key is backed up in the cloud with the device backup. This field is false by default.
|
cloud | No | boolean |
Indicates a key which is stored in the cloud and is a special key for backups. The type should be ASCIIBLOB and the keydata contains the backup-specific part of the URL for fetching the key.
|
Returns
{ "returnValue" : boolean, "errorText" : string }
Argument | Required | Type | Description |
---|---|---|---|
returnValue | Yes | boolean |
true (success) or false (failure).
|
errorText | No | string | Error message returned on failure. |
Example
// The following base64 encoding functionality is something YOU need to provide var KeyDataB64 = Base64.encode("123456"); this.controller.serviceRequest("palm://com.palm.keymanager/", { method: "store", parameters: { "keyname" : "MyKey", "keydata" : KeyDataB64, "type" : "AES", "nohide" : true }, onSuccess: function(e){ Mojo.Log.info("Store key success"); }, onFailure: function(e){ Mojo.Log.info("Store key failure, err="+JSON.stringify(e)); } });