From 828b861fcec6238b91f2e33630d841c1e27d0508 Mon Sep 17 00:00:00 2001 From: Matt Perry Date: Mon, 26 Oct 2015 15:14:01 -0400 Subject: [PATCH] Change signing code to use shared flx package. --- .../flutter_tools/lib/src/commands/build.dart | 33 ++----- packages/flutter_tools/lib/src/signing.dart | 94 ------------------- packages/flutter_tools/pubspec.yaml | 1 + 3 files changed, 11 insertions(+), 117 deletions(-) delete mode 100644 packages/flutter_tools/lib/src/signing.dart diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart index cc421b5ac69..1360f39ee9d 100644 --- a/packages/flutter_tools/lib/src/commands/build.dart +++ b/packages/flutter_tools/lib/src/commands/build.dart @@ -7,11 +7,10 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:archive/archive.dart'; -import 'package:cipher/cipher.dart'; -import 'package:cipher/impl/client.dart'; import 'package:yaml/yaml.dart'; -import '../signing.dart'; +import 'package:flx/bundle.dart'; +import 'package:flx/signing.dart'; import '../toolchain.dart'; import 'flutter_command.dart'; @@ -100,16 +99,6 @@ ArchiveFile _createFile(String key, String assetBase) { return new ArchiveFile.noCompress(key, content.length, content); } -// Writes a 32-bit length followed by the content of [bytes]. -void _writeBytesWithLength(File outputFile, List bytes) { - if (bytes == null) - bytes = new Uint8List(0); - assert(bytes.length < 0xffffffff); - ByteData length = new ByteData(4)..setUint32(0, bytes.length, Endianness.LITTLE_ENDIAN); - outputFile.writeAsBytesSync(length.buffer.asUint8List(), mode: FileMode.APPEND); - outputFile.writeAsBytesSync(bytes, mode: FileMode.APPEND); -} - ArchiveFile _createSnapshotFile(String snapshotPath) { File file = new File(snapshotPath); List content = file.readAsBytesSync(); @@ -139,7 +128,6 @@ class BuildCommand extends FlutterCommand { @override Future run() async { - initCipher(); String compilerPath = argResults['compiler']; if (compilerPath == null) @@ -193,16 +181,15 @@ class BuildCommand extends FlutterCommand { archive.addFile(file); } - ECPrivateKey privateKey = await loadPrivateKey(privateKeyPath); - ECPublicKey publicKey = publicKeyFromPrivateKey(privateKey); - - File outputFile = new File(outputPath); - outputFile.writeAsStringSync('#!mojo mojo:sky_viewer\n'); + KeyPair keyPair = KeyPair.readFromPrivateKeySync(privateKeyPath); Uint8List zipBytes = new Uint8List.fromList(new ZipEncoder().encode(archive)); - Uint8List manifestBytes = serializeManifest(manifestDescriptor, publicKey, zipBytes); - _writeBytesWithLength(outputFile, signManifest(manifestBytes, privateKey)); - _writeBytesWithLength(outputFile, manifestBytes); - outputFile.writeAsBytesSync(zipBytes, mode: FileMode.APPEND, flush: true); + Bundle bundle = new Bundle.fromContent( + path: outputPath, + manifest: manifestDescriptor, + contentBytes: zipBytes, + keyPair: keyPair + ); + bundle.writeSync(); return 0; } } diff --git a/packages/flutter_tools/lib/src/signing.dart b/packages/flutter_tools/lib/src/signing.dart deleted file mode 100644 index d3390a6d590..00000000000 --- a/packages/flutter_tools/lib/src/signing.dart +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:asn1lib/asn1lib.dart'; -import 'package:bignum/bignum.dart'; -import 'package:cipher/cipher.dart'; - -// The ECDSA algorithm parameters we're using. These match the parameters used -// by the Flutter updater package. -final ECDomainParameters _ecDomain = new ECDomainParameters('prime256v1'); -final String kSignerAlgorithm = 'SHA-256/ECDSA'; -final String kHashAlgorithm = 'SHA-256'; - -final SecureRandom _random = _initRandom(); - -SecureRandom _initRandom() { - // TODO(mpcomplete): Provide a better seed here. External entropy source? - final Uint8List key = new Uint8List(16); - final KeyParameter keyParam = new KeyParameter(key); - final ParametersWithIV params = new ParametersWithIV(keyParam, new Uint8List(16)); - SecureRandom random = new SecureRandom('AES/CTR/AUTO-SEED-PRNG') - ..seed(params); - return random; -} - -// Returns a serialized manifest, with the public key and hash of the content -// included. -Uint8List serializeManifest(Map manifestDescriptor, ECPublicKey publicKey, Uint8List zipBytes) { - if (manifestDescriptor == null) - return null; - final List kSavedKeys = [ - 'name', - 'version', - 'update-url' - ]; - Map outputManifest = new Map(); - manifestDescriptor.forEach((key, value) { - if (kSavedKeys.contains(key)) - outputManifest[key] = value; - }); - - if (publicKey != null) - outputManifest['key'] = BASE64.encode(publicKey.Q.getEncoded()); - - Uint8List zipHash = new Digest(kHashAlgorithm).process(zipBytes); - BigInteger zipHashInt = new BigInteger.fromBytes(1, zipHash); - outputManifest['content-hash'] = zipHashInt.intValue(); - - return new Uint8List.fromList(UTF8.encode(JSON.encode(outputManifest))); -} - -// Returns the ASN.1 encoded signature of the input manifestBytes. -List signManifest(Uint8List manifestBytes, ECPrivateKey privateKey) { - if (manifestBytes == null || privateKey == null) - return []; - Signer signer = new Signer(kSignerAlgorithm); - PrivateKeyParameter params = new PrivateKeyParameter(privateKey); - signer.init(true, new ParametersWithRandom(params, _random)); - ECSignature signature = signer.generateSignature(manifestBytes); - ASN1Sequence asn1 = new ASN1Sequence() - ..add(new ASN1Integer(signature.r)) - ..add(new ASN1Integer(signature.s)); - return asn1.encodedBytes; -} - -ECPrivateKey _asn1ParsePrivateKey(ECDomainParameters ecDomain, Uint8List privateKey) { - ASN1Parser parser = new ASN1Parser(privateKey); - ASN1Sequence seq = parser.nextObject(); - assert(seq.elements.length >= 2); - ASN1OctetString keyOct = seq.elements[1]; - BigInteger d = new BigInteger.fromBytes(1, keyOct.octets); - return new ECPrivateKey(d, ecDomain); -} - -Future loadPrivateKey(String privateKeyPath) async { - File file = new File(privateKeyPath); - if (!file.existsSync()) - return null; - List bytes = file.readAsBytesSync(); - return _asn1ParsePrivateKey(_ecDomain, new Uint8List.fromList(bytes)); -} - -ECPublicKey publicKeyFromPrivateKey(ECPrivateKey privateKey) { - if (privateKey == null) - return null; - ECPoint Q = privateKey.parameters.G * privateKey.d; - return new ECPublicKey(Q, privateKey.parameters); -} diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml index b992a472c5a..8c782bda8b9 100644 --- a/packages/flutter_tools/pubspec.yaml +++ b/packages/flutter_tools/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: args: ^0.13.0 asn1lib: ^0.4.1 cipher: ^0.7.1 + flx: ^0.0.1 crypto: ^0.9.1 mustache4dart: ^1.0.0 path: ^1.3.0