{
"info": {
"author": "ARM",
"author_email": "support@arm.com",
"bugtrack_url": null,
"classifiers": [],
"description": "## Update manifest creation\n\n### Manifest tool\n\nThe manifest tool creates and parses manifest files. You can use it as a command-line utility or Python package.\n\n### Installation\n\nThe manifest tool is compatible both with Python 2.7.11 and later and with Python 3.5.1 and later.\n\nThere are 4 options for installing the manifest tool, but all use `pip`:\n\n1. Install from PyPi with pip.\n\n ```\n $ pip install manifest-tool\n ```\n\n1. Install from GitHub over HTTPS.\n\n ```\n $ pip install git+https://github.com/ARMmbed/manifest-tool.git\n ```\n\n1. Install from GitHub over SSH.\n\n ```\n $ pip install git+ssh://git@github.com/ARMmbed/manifest-tool.git\n ```\n\n1. Install from a local copy of this repository.\n\n ```\n $ pip install .\n ```\n\n**Note:** This repository includes `setup.py`, but it does not work on all systems. Please use `pip` for the best experience.\n\nSee [Debugging Installation](#debugging-installation) if these steps do not work.\n\n### Set up the Device Management Python SDK (optional)\n\nYou can use the SDKs to automate uploading your manifest to Device Management (as detailed below); this requires installing the SDKs. If you do not want to install the SDKs, use the Update service API or Device Management Portal to upload the manifest.\n\nInstall the the Python SDK directly from GitHub:\n```\n $ pip install git+https://github.com/ARMmbed/mbed-cloud-sdk-python.git\n```\n\n### Workflow\n\nThe Update client workflow has three stages:\n\n1. Send a payload to an update medium, for example a web service, a removable storage device or a broadcast system.\n1. Create a manifest for that payload. The manifest includes the hash and size of the payload along with its URI on the update medium.\n1. Send that manifest to an update medium.\n\n### Quick Start\n\nIn a new project that will support the Update client, run the following command:\n\n```\n$ manifest-tool init -d \"\" -m \"\" -a \"\" -S \"\"\n```\n\nNote that you do not need to enter `-S` for the production environment.\n\nThe manifest tool is able to use the Device Management Python SDK to upload firmware and manifests to Device Management. If you do not require this feature, you can call `manifest-tool init` with fewer arguments:\n\n```\n$ manifest-tool init -d \"\" -m \"\"\n```\n\nThis will create several files:\n* A certificate in `.update-certificates/default.der`.\n* A matching private key in `.update-certificates/default.key.pem`.\n* A set of default settings in `.manifest_tool.json`.\n* Device Management settings in `.mbed_cloud_config.json`.\n\nThe default settings include:\n* A unique vendor identifier, based on the domain name supplied to `init`.\n* A unique model identifier, based on the vendor identifier and the model name supplied to `init`.\n* The path of the certificate and private key.\n\nIf you do not want to enter the subject information for your certificate (country, state, city, organization and so on), add the `-q` flag to the command above.\n\n**Note:** The certificate created in `manifest-tool init` is not suitable for production. You should avoid using it except in testing and development. To create a certificate for production purposes, please use an air-gapped computer or a Hardware Security Module. You should conduct a security review on your manifest signing infrastructure, since it is the core of the security guarantees for Update client.\n\n#### Single-device update\nOnce you have run `manifest-tool init`, you can perform updates on a single device by:\n\n```sh\n$ manifest-tool update device -p -D \n```\n\nThis will perform several actions:\n1. Upload the payload to Device Management.\n1. Hash the payload and create a manifest that links to its location in Device Management.\n1. Create an update campaign for the supplied device ID, with the newly created manifest.\n1. Start the campaign.\n1. Wait for the campaign to complete.\n1. Delete the payload, manifest and update campaign out of Device Management.\n\nThis allows development with a device for testing purposes.\n\n#### Multidevice update\n\nIf more than one device needs updating, you can use Device Management Portal to create device filters that can include many devices into an update campaign. First, you need a manifest. Once you have run `manifest-tool init`, you can create manifests by:\n\n```\n$ manifest-tool update prepare -p \n```\n\nOptionally, a name and description for the payload and corresponding manifest can be provided:\n\n```\n$ manifest-tool update prepare -p -n -d \\\n --manifest-name --manifest-description \n```\n\nBoth methods of creating a manifest use the defaults created in `manifest-tool init`. You can override each default using an input file or command-line arguments. See below for more details.\n\nOnce `manifest-tool update prepare` has been executed the manifest file is automatically uploaded to Device Management and you can then create and start an update campaign using the Device Management portal.\n\n### External signing tool\n\nThe documentation can be found [here](https://cloud.mbed.com/docs/current/updating-firmware/external-signing-tools.html).\n\n### Debugging Installation\n\nSome platforms require `python-dev` or `python3-dev` to install Python's cryptography library, which is a dependency of the manifest tool. For example, on Ubuntu, run:\n\n```sh\n$ sudo apt-get install python-dev\n```\n\n### Advanced usage\n\nThe manifest tool allows for significantly more flexibility than the model above shows. You can override each of the defaults that `manifest-tool init` sets by using the command-line or an input file. The manifest tool supports a variety of commands. You can print a full list of commands by using `manifest-tool --help`.\n\n\n#### Advanced creation Prerequisites\n\nTo create a manifest, you must provide an ECC certificate and private key. The certificate must be an ECC secp256r1 DER encoded certificate. Best practice is for an authority the target device trusts to sign this certificate.\n\nThe Update client on the target device must have this certificate available, or the certificate must be signed by a certificate that is available on the target device.\n\n##### Creating a certificate for production use\n\nTo use a certificate in production, please use a Hardware Security Module or an air-gapped computer to create the certificate. You can then use this device to create signatures for manifests. If you use certificate delegation, you can use the HSM or air-gapped computer to sign the delegated certificates. You should perform a security review on your signing infrastructure.\n\n##### Creating a certificate for development use\n\n**For testing and evaluation only**\n\nProviding a self-signed certificate is adequate for testing purposes. There are many methods for creating a self-signed certificate. The manifest tool provides two commands: `init` and `cert create`, which creates a self-signed certificate. OpenSSL can also produce one, but we do not recommended this on Mac OS X, due to the old version of OpenSSL that ships with it, nor on Windows, because you must install OpenSSL separately.\n\n###### Creating a self-signed certificate with manifest-tool init\n\nRunning `manifest-tool init` in a project for the first time also creates a self-signed certificate. If a certificate already exists in `.update-certificates/default.der`, then no certificate is created. If you already have a certificate and private key, you should pass those in to `manifest-tool init` using the `-c ` and `-k ` arguments.\n\n###### Creating a self-signed certificate with manifest-tool cert create\n\nThe manifest tool provides a certificate creation command, which creates a self-signed certificate:\n\n```\nmanifest-tool cert create -V -K -o \n```\n\nIn addition, you can provide subject arguments on the command-line to specify the country, state, locality, organization name and common name of the certificate's subject.\n\n###### Creating a self-signed certificate with OpenSSL\n\nUsing OpenSSL, you can create a self-signed ECC certificate, but there are several caveats:\n\n* OpenSSL defaults to SHA1 on many platforms, which is unsecure.\n* On some platforms, it is not possible to specify SHA256.\n* OpenSSL does not support ECC on some platforms.\n\n**Unless the version of OpenSSL your platform provides is at least 1.0.1, we do not recommend you use OpenSSL.**\n\nIn order to generate a self-signed certificate, follow these steps:\n\n```\nopenssl ecparam -genkey -name prime256v1 -out key.pem\nopenssl req -new -sha256 -key key.pem -out csr.csr\nopenssl req -x509 -sha256 -days 365 -key key.pem -in csr.csr -outform der -out certificate.der\n```\n\n**Note:** `prime256v1` is an alias for `secp256r1`.\n\nNow, verify that OpenSSL used SHA256 to sign the certificate. Some OpenSSL installations ignore the `-sha256` parameter and create a SHA1 signature. This is a problem because of the deprecation of SHA1 due to weak security.\n\n```\nopenssl req -in csr.csr -text -noout | grep -i \"Signature.*SHA256\"\n```\n\n#### Examining a certificate\n\nTo view the information in a certificate, use OpenSSL's x509 command:\n\n```\nopenssl x509 -inform der -in certificate.der -text -noout\n```\n\n#### Obtaining a certificate fingerprint\n\nThe manifest tool fingerprints certificates during the manifest creation process. If you used `manifest-tool init`, then it is not necessary to extract the fingerprint.\n\nYou can use OpenSSL to check the manifest-tool's output or to obtain the certificate fingerprint if `manifest-tool init` was not used:\n\n```\nopenssl x509 -inform der -in certificate.der -sha256 -fingerprint -noout\n```\n\nOpenSSL reports the fingerprint of the certificate:\n\n```\nSHA256 Fingerprint=00:01:02:03:04:05:06:07:08:09:0A:0B:0C:0D:0E:0F:10:11:12:13:14:15:16:17:18:19:1A:1B:1C:1D:1E:1F\n```\n\nWhen a C byte array is a requirement (for example, in the Update client's certificate manager), this must be converted to one, for example by finding all `:` and replacing with `, 0x`.\n\n```\n0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F\n```\n\nThis can be done in an automated way on systems that support the `sed` command. For example:\n\n```\nopenssl x509 -inform der -in certificate.der -noout -fingerprint -sha256 | sed -e \"s/.*=\\(.*\\)/\\1/\" | sed -e \"s/:/, 0x/g\" | sed -e \"s/\\(.*\\)/uint8_t arm_uc_default_fingerprint[] = {0x\\1};/\"\nuint8_t arm_uc_default_fingerprint[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};\n```\n\nTo turn the certificate itself into a byte array, use `xxd` or a similar tool for printing hexadecimal values:\n\n```\nxxd -i certificate.der\n```\n\nThe manifest tool automates this process as part of the `init` command and places the output in `update_default_resources.c`.\n\n#### Creating manifests\n\nThere are three ways to provide data to the manifest tool. It parses a JSON input file, which can contain all of the information used to create the manifest. If information is missing from the input file, the manifest tool checks for a file that contains defaults in the current working directory (`.manifest_tool.json`). You can create this file most easily using `manifest-tool init`. The third way of providing data is command-line arguments; you can override many of the fields the manifest tool uses on the command-line.\n\nCurrently, you need manifests to use SHA256 for hashes, ECDSA signatures on the secp256r1 curve, with no encryption. The manifest tool calls this encryption mode `none-ecc-secp256r1-sha256`. Future versions of the manifest tool will add support for payload encryption.\n\n**Note:** The Update client currently only supports binary payloads, so the payload type is assumed to be binary.\n\n##### Mode none-ecc-secp256r1-sha256\n\n###### Minimum requirements for none-ecc-secp256r1-sha256\n\nThe minimum requirements for creating a manifest with unencrypted payload are:\n\n* The cryptographic mode to use (none-ecc-secp256r1-sha256, in this case).\n* The payload URI.\n* One of:\n * The URI of a certificate to be used for signing the manifest.\n * A local file that is a certificate to be used for signing the manifest.\n* A local file that is the signing key for that certificate.\n* One of:\n * The vendor ID and device class ID.\n * The device ID.\n\n###### What mode none-ecc-secp256r1-sha256 does\n\nIn this mode, the manifest tool creates and signs a manifest; the payload is unencrypted. The target device(s) must already have the provided certificate or must provide a way to fetch that certificate.\n\nThe manifest tool:\n\n1. Fetches and hashes the payload. It loads the payload from a local file.\n1. Fetches and fingerprints the certificate (either from the provided URI or the local file).\n1. Creates the inner part of the manifest, containing:\n 1. The provided IDs.\n 1. The payload URI.\n 1. The payload size.\n 1. The payload hash.\n1. Hashes the inner part of the manifest.\n1. Uses the hash and the certificate private key to sign the inner part of the manifest.\n1. Wraps the inner part, hash, signature, certificate fingerprint and certificate URI in the outer part of the manifest.\n\n###### Using mode none-ecc-secp256r1-sha256\n\nWhen you invoke the manifest tool to create a manifest with encryption mode `none-ecc-secp256r1-sha256`, the information below must be provided. The manifest tool can find most of the information in more than one way. You can provide every item in the input file. Alternative options are provided in parentheses.\n\n* The type of hashing, signing and encryption to use (calculated from mandatory inputs if absent).\n* Vendor ID (extracted from defaults if absent).\n* Class ID (extracted from defaults if absent).\n* Payload URI (overridden by `-u`).\n* Payload File (overridden by `-p`).\n* Description (defaults to empty).\n* Certificate used for signing (extracted from defaults if absent).\n\n###### Example 1:\n\nProviding all fields by using the input file:\n\n```JSON\n{\n \"encryptionMode\" : \"none-ecc-secp256r1-sha256\",\n \"vendorId\" : \"\",\n \"classId\" : \"\",\n \"payloadUri\" : \"http://path.to/payload.bin\",\n \"payloadFile\" : \"/path/to/payload.bin\",\n \"description\" : \"Description of the update\",\n \"certificates\": [\n { \"uri\": \"http://path.to/certificate.der\" , \"file\" : \"/path/to/certificate.der\" }\n ]\n}\n```\n\nTo create a manifest with this information, call the manifest tool:\n\n```sh\n$ manifest-tool create -i input.json -o output.manifest -k certificate_key.pem\n```\n\n###### Example 2:\n\nProviding no input file. Run this command one time in the root of the project:\n\n```sh\n$ manifest-tool init -d \"\" -m \"\"\n```\n\nThen, use this command to prepare an update:\n\n```sh\n$ manifest-tool create -u -p -o \n```\n\n#### Manifest creation input file\n\nIf a `.manifest_tool.json` file is present in the current working directory when you run `manifest-tool create`, `manifest-tool update prepare` or `manifest-tool update device`, the manifest tool loads default values from this file. It overrides these values with the contents of the manifest creation input file. Then, it uses any command-line options to override the contents of the manifest creation input file. If you have used `manifest-tool init` to initialize the current working directory and you use `manifest-tool create -p -u `, then the input file is optional.\n\nThis means that all fields in the manifest creation input file are optional. However, the `.manifest_tool.json` defaults file, the manifest creation input file or the command-line must specify some fields:\n\n1. `vendorId`.\n1. `classId`.\n1. `payloadUri`.\n1. `payloadFile` or `payloadHash`.\n1. `certificateFingerprint` or `certificateFile`.\n1. `privateKey`.\n\nThe manifest creation input file follows the JSON representation of the [manifest format v1 specification]. Because there is a significant quantity of nesting in the input fields, there are short-hands for most fields.\n\nSeveral parts in a nested structure comprise the manifest creation input file:\n\n1. Signed resource.\n 1. Manifest.\n 1. Encryption info.\n 1. Payload info.\n 1. Signature block.\n\n##### Signed resource\n\nThe signed resource is the top level object in the input file. Because of this, its name does not appear. It contains only two objects:\n\n1. Manifest.\n1. Signature block.\n\n```JSON\n{\n \"resource\" : {\n \"resource\" : {\n \"manifest\" : \n }\n },\n \"signature\" : \n}\n```\n\n* `manifest`: See the [Manifest] section.\n* `signature`: See the [Signature block] section.\n\nIf you wish to use short-hand parameters, you must place them at this level, within the `SignedResource` object (the un-named top-level JSON object). For example, to use the shorthand for specifying a payload hash, add the `payloadHash` short-hand as below:\n\n```JSON\n{\n \"resource\" : {\n \"resource\" : {\n \"manifest\" : \n }\n },\n \"payloadHash\" : ,\n \"signature\" : \n}\n```\n\nThe full list of short-hand parameters is available in [Short-hand parameters].\n\n##### Manifest\n\nThe manifest object contains several fields and one subobject.\n\n```JSON\n{\n \"payload\": ,\n \"description\": \"Description of the update\",\n \"vendorId\": ,\n \"classId\": ,\n \"precursorDigest\" : ,\n \"applyImmediately\": true,\n \"priority\" : ,\n \"encryptionMode\": {\n \"enum\": \"none-ecc-secp256r1-sha256\"\n },\n \"vendorInfo\": \n}\n```\n\n* `payload`: See the [Payload] section.\n* `description`: A free-text description of the payload. This should be small.\n* `vendorId`: Hex representation of the 128-bit RFC4122 GUID that represents the vendor.\n* `classId`: Hex representation of the 128-bit RFC4122 GUID that represents the device class that the update targets. Device classes can mean devices of a given type (for example, smart lights) or model numbers. This allows targeting of updates to particular groups of devices based on the attributes they share, where a device class represents each set of attributes. Because of this, each device can have multiple device classes. Device Management Update client only supports the use of device classes to represent model numbers/revisions.\n* `precursorDigest` - You can use this field in delta updates to specify the image that must already be present on the device for the delta update to produce the correct result.\n* `precursorFile` - A path to a local copy of the precursor. The manifest tool uses this file to calculate the `precursorDigest`. This is not needed if you specify the precursor hash.\n* `applyImmediately`: This is always assumed to be true. Device Management Update client does not currently implement it.\n* `priority` - The importance of the update. You can use this integer field to tell your application how important an update is, so that it can decide whether to use it or not. The meanings of the values of `priority` are application-defined. 0 typically means \"mandatory\" and increasing values have lower priority.\n* `encryptionMode`: Update client only supports two values:\n * `none-ecc-secp256r1-sha256`: SHA256 hashing, ECDSA signatures, using the secp256r1 curve. This does not use payload encryption (Update client only).\n * `none-psk-aes-128-ccm-sha256`: SHA256 hashing, manifest digest is authenticated with AES-CCM-128. This does not use payload encryption (Update Client Lite only).\n* `vendorInfo`: You can place proprietary information in this field. We recommend DER encoding because this allows you to reuse the Update client's general purpose DER parser.\n\n##### Payload\n\nThe payload section describes the payload object.\n\n```JSON\n{\n \"storageIdentifier\": ,\n \"reference\": {\n \"hash\": ,\n \"size\": ,\n \"uri\": \"http://path.to/payload\",\n \"file\": \n }\n}\n```\n\n* `storageIdentifier`: A number that the device recognizes for where to store the payload.\n* `hash`: The SHA256 hash of the payload.\n* `size`: The size of the payload.\n* `uri`: The URI from which the target devices should acquire the payload.\n* `file`: A path to a local copy of the payload. The manifest tool uses this file to calculate the payload hash and payload size. This is not needed if you specify the payload hash and size in the input file.\n* `installedDigest`: You can use this field with delta updates to specify the result of applying an update. The digest in `reference` specifies the digest of the downloaded object. For delta updates, a second digest is needed to ensure that the result of any processing applied to the resource results in the correct payload image.\n* `installedSize`: You can use this field in delta updates to specify the size of an image after the delta update processing is applied.\n* `installedFile`: You can use this field to specify a path to a local copy of the desired result of a delta update. The manifest tool uses this file to calculate the `installedDigest` and `installedFile`. This is not needed if you specify `installedDigest` and `installedFile` in the input file.\n\n##### Signature block\n\nUse the signature block to select the certificate the device should use to verify the signature of the manifest.\n\n```JSON\n{\n \"signatures\": [\n {\n \"certificates\": [\n {\n \"uri\": \"\",\n \"fingerprint\": \"\",\n \"file\": \"/path/to/certificate.der\"\n }\n ]\n }\n ]\n}\n```\n\n* `certificates`: A list of URI/fingerprint pairs. The first certificate in the list must match the private key that you provied to the manifest tool to sign the manifest, supplied through the `-k` command-line option. Each certificate must sign the certificate before it in the list. The last certificate in the list should be the root of trust in the device and can have an empty URI. Instead of a `fingerprint`, you can provide a `file` and the manifest tool will calculate the fingerprint. Note that Device Management Update client does not provide a mechanism to fetch certificates in this list. Implementing this feature requires the developer to override `arm_uc_kcm_cert_fetcher`. By default, Device Management Update client expects to have one certificate and that this certificate must verify all manifests.\n\n##### Short-hand parameters\n\n* `encryptionMode`: Sets the `encryptionMode` in `manifest`.\n* `payloadFile`: Sets the `file` in `payload`.\n* `payloadUri`: Sets the `uri` in `payload`.\n* `payloadHash`: Sets the `hash` in `payload`.\n* `payloadSize`: Sets the `size` in `payload`.\n* `vendorInfo`: Sets the `vendorInfo` in `manifest`.\n* `vendorId`: Sets the `vendorId` in `manifest`.\n* `classId`: Sets the `classId` in `manifest`.\n* `description`: Sets the `description` in `manifest`\n* `certificates`: Sets the `certificates` in `signature`.\n* `installedSize` : Sets the `installedSize` in `payload`\n* `installedDigest` : Sets the `installedDigest` in `payload`\n* `installedFile` : Sets the `installedFile` in `payload`\n* `priority` : Sets the `priority` in `manifest`\n* `precursorDigest` : Sets the `precursorDigest` in `manifest`\n* `precursorFile` : Sets the `precursorFile` in `manifest`\n\n\nYou can also override many of these parameters on the command-line. See `manifest-tool create --help` for more information.\n\n#### Parsing manifests\n\n##### Command-line\n\nTo convert a manifest to JSON:\n\n```sh\nmanifest-tool parse -i input.manifest\n```\n\nTo make the JSON more readable, use the `-j` flag.\n\n```sh\nmanifest-tool parse -ji input.manifest\n```\n\n##### Python library\n\nTo convert a manifest file to a Python dictionary:\n\n```\nimport manifesttool.parse\n\nmanifest = open('test0.manifest', 'rb').read()\nparsed_manifest = manifesttool.parse.parseManifest(manifest)\nprint(parsed_manifest)\n```\n\n### Development\n\nInstall all required packages, and create a virtual environment:\n\n```\npip2 install virtualenv\nmkdir -p ~/virtualenvs\nvirtualenv ~/virtualenvs/manifest-tool\nsource ~/virtualenvs/manifest-tool/bin/activate\n```\n\n\n",
"description_content_type": "text/markdown",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/ARMmbed/manifest-tool",
"keywords": "",
"license": "",
"maintainer": "",
"maintainer_email": "",
"name": "manifest-tool",
"package_url": "https://pypi.org/project/manifest-tool/",
"platform": "",
"project_url": "https://pypi.org/project/manifest-tool/",
"project_urls": {
"Homepage": "https://github.com/ARMmbed/manifest-tool"
},
"release_url": "https://pypi.org/project/manifest-tool/1.5.2/",
"requires_dist": [
"ecdsa (>=0.13)",
"cryptography (>=2.0.0)",
"pyasn1 (<0.3.0,>=0.2.1)",
"asn1ate (>=0.5)",
"pyparsing (>=2.1.0)",
"future (>=0.16.0)",
"urllib3 (>=1.20)",
"colorama (<0.4.0,>=0.3.9)",
"protobuf (<3.6.0,>=3.5.0)"
],
"requires_python": "",
"summary": "Tool/lib to create and parse manifests",
"version": "1.5.2"
},
"last_serial": 5340221,
"releases": {
"1.4.6": [
{
"comment_text": "",
"digests": {
"md5": "ccf697ceb6aa85dd2a988d9625bc3c16",
"sha256": "ffb9d652dd8e10ab3f41af4e1d6b44eb87a840cceeaadc3d2b1bc5a75de3abd5"
},
"downloads": -1,
"filename": "manifest-tool-1.4.6.tar.gz",
"has_sig": false,
"md5_digest": "ccf697ceb6aa85dd2a988d9625bc3c16",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 55045,
"upload_time": "2018-10-31T14:21:41",
"url": "https://files.pythonhosted.org/packages/a9/9f/10ef2cda2e774d61c3cac1e7a413ef264d3a06b775e8604fabfc1f48d61b/manifest-tool-1.4.6.tar.gz"
}
],
"1.4.7": [
{
"comment_text": "",
"digests": {
"md5": "35a14221eb1006dc5684aa00f2b45441",
"sha256": "2bb595b481eec9de6f6981b0a5aa7ce14b89ec09cf6ac9fcdaffc8a6a13dae2c"
},
"downloads": -1,
"filename": "manifest-tool-1.4.7.tar.gz",
"has_sig": false,
"md5_digest": "35a14221eb1006dc5684aa00f2b45441",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 49651,
"upload_time": "2018-11-05T16:26:18",
"url": "https://files.pythonhosted.org/packages/61/00/fb183d44ad303ef3462f04398a94c8ce09ba049000f616c630d1e83bb07c/manifest-tool-1.4.7.tar.gz"
}
],
"1.4.8": [
{
"comment_text": "",
"digests": {
"md5": "cbae6d95396e46e9347924fcbc94aade",
"sha256": "dec49103aae547926040515e1bd5a252fdd3e07391040e9111588c53d218c79a"
},
"downloads": -1,
"filename": "manifest-tool-1.4.8.tar.gz",
"has_sig": false,
"md5_digest": "cbae6d95396e46e9347924fcbc94aade",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 64158,
"upload_time": "2019-03-13T15:40:30",
"url": "https://files.pythonhosted.org/packages/39/d1/fed6eac5f5ade9d930299f6372c7e5b556bfd4a75e2e3562edd8f9234f77/manifest-tool-1.4.8.tar.gz"
}
],
"1.5.0": [
{
"comment_text": "",
"digests": {
"md5": "90a109a29cad1b8749f6d9270aef4ed9",
"sha256": "865235b40e949ac07fdcf3c7a163de95471af5cf6d132dff067ba721ee112db6"
},
"downloads": -1,
"filename": "manifest_tool-1.5.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "90a109a29cad1b8749f6d9270aef4ed9",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 71632,
"upload_time": "2019-05-30T21:58:36",
"url": "https://files.pythonhosted.org/packages/fc/b0/ced94d45f468dc8573eec06bc186507632b5f96d17209a52621369957327/manifest_tool-1.5.0-py2-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "e6499880182e6746217bdd8dd342a0e2",
"sha256": "5f02dfc9dac18fb84d63e0b351d589c627d92f5e95305e578de8a885b624ac09"
},
"downloads": -1,
"filename": "manifest_tool-1.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e6499880182e6746217bdd8dd342a0e2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 75228,
"upload_time": "2019-05-30T21:55:05",
"url": "https://files.pythonhosted.org/packages/f8/08/235074b83ec3783ab573b2e47de0c8d25f733f07f5b4615563f6629be4e8/manifest_tool-1.5.0-py3-none-any.whl"
}
],
"1.5.2": [
{
"comment_text": "",
"digests": {
"md5": "9f298e26de455557b7ee583420ce3293",
"sha256": "78068f21313d5ca5d6a1f4d23b2179f45cb99ac5835755be2daad5039899c344"
},
"downloads": -1,
"filename": "manifest_tool-1.5.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9f298e26de455557b7ee583420ce3293",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 75203,
"upload_time": "2019-05-30T23:48:47",
"url": "https://files.pythonhosted.org/packages/73/3c/acf359b9df998153aa4dc70684d202b8b283cb4156f60d2050232d35b49f/manifest_tool-1.5.2-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "bf47b98a7538061759d626d76fd2cfad",
"sha256": "acd6aa8b7b59789511b1b5a47bc25a2a593c75eb857eae8f59db8742f64c56a3"
},
"downloads": -1,
"filename": "manifest-tool-1.5.2.tar.gz",
"has_sig": false,
"md5_digest": "bf47b98a7538061759d626d76fd2cfad",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 54038,
"upload_time": "2019-05-30T23:48:49",
"url": "https://files.pythonhosted.org/packages/ea/df/59413d8b568514730c718a251bdf140ce3d32aeb5c1ac512d6f9507d2a44/manifest-tool-1.5.2.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "9f298e26de455557b7ee583420ce3293",
"sha256": "78068f21313d5ca5d6a1f4d23b2179f45cb99ac5835755be2daad5039899c344"
},
"downloads": -1,
"filename": "manifest_tool-1.5.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9f298e26de455557b7ee583420ce3293",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 75203,
"upload_time": "2019-05-30T23:48:47",
"url": "https://files.pythonhosted.org/packages/73/3c/acf359b9df998153aa4dc70684d202b8b283cb4156f60d2050232d35b49f/manifest_tool-1.5.2-py3-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "bf47b98a7538061759d626d76fd2cfad",
"sha256": "acd6aa8b7b59789511b1b5a47bc25a2a593c75eb857eae8f59db8742f64c56a3"
},
"downloads": -1,
"filename": "manifest-tool-1.5.2.tar.gz",
"has_sig": false,
"md5_digest": "bf47b98a7538061759d626d76fd2cfad",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 54038,
"upload_time": "2019-05-30T23:48:49",
"url": "https://files.pythonhosted.org/packages/ea/df/59413d8b568514730c718a251bdf140ce3d32aeb5c1ac512d6f9507d2a44/manifest-tool-1.5.2.tar.gz"
}
]
}