124 lines
6.0 KiB
Dart
124 lines
6.0 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:bignum/bignum.dart';
|
|
import 'package:flx/signing.dart';
|
|
import 'package:pointycastle/pointycastle.dart' hide CipherParameters;
|
|
import 'package:test/test.dart';
|
|
|
|
Future<Null> main() async {
|
|
// The following constant was generated via the openssl shell commands:
|
|
// openssl ecparam -genkey -name prime256v1 -out privatekey.pem
|
|
// openssl ec -in privatekey.pem -outform DER | base64
|
|
const String kPrivateKeyBase64 = 'MHcCAQEEIG4Xt+MgsdP/o89kAHz7EVVLKkN+DUfpaBtZfMyFGbUgoAoGCCqGSM49AwEHoUQDQgAElPtbBVPPqKHYXYAgHaxB2hL6sXeFc99YLijTAuAPe2Nbhywan+v4k+nFm0TJJW/mkV+nH+fyBZ98t4UcFCqkOg==';
|
|
final List<int> kPrivateKeyDER = BASE64.decode(kPrivateKeyBase64);
|
|
|
|
// Unpacked values of the above private key.
|
|
const int kPrivateKeyD = 0x6e17b7e320b1d3ffa3cf64007cfb11554b2a437e0d47e9681b597ccc8519b520;
|
|
const int kPublicKeyQx = 0x94fb5b0553cfa8a1d85d80201dac41da12fab1778573df582e28d302e00f7b63;
|
|
const int kPublicKeyQy = 0x5b872c1a9febf893e9c59b44c9256fe6915fa71fe7f2059f7cb7851c142aa43a;
|
|
|
|
// Test manifest.
|
|
final Map<String, dynamic> kManifest = <String, dynamic>{
|
|
'name': 'test app',
|
|
'version': '1.0.0'
|
|
};
|
|
|
|
// Simple test byte pattern (flat and in chunked form) and its SHA-256 hash.
|
|
final Uint8List kTestBytes = new Uint8List.fromList(<int>[1, 2, 3]);
|
|
final List<Uint8List> kTestBytesList = <Uint8List>[
|
|
new Uint8List.fromList(<int>[1, 2]), new Uint8List.fromList(<int>[3])];
|
|
final int kTestHash = 0x039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81;
|
|
|
|
// Set up a key generator.
|
|
CipherParameters cipher = CipherParameters.get();
|
|
cipher.seedRandom();
|
|
ECKeyGeneratorParameters ecParams = new ECKeyGeneratorParameters(cipher.domain);
|
|
ParametersWithRandom<ECKeyGeneratorParameters> keyGeneratorParams =
|
|
new ParametersWithRandom<ECKeyGeneratorParameters>(ecParams, cipher.random);
|
|
KeyGenerator keyGenerator = new KeyGenerator('EC');
|
|
keyGenerator.init(keyGeneratorParams);
|
|
|
|
test('can read openssl key pair', () {
|
|
AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
|
|
expect(keyPair != null, equals(true));
|
|
ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
|
|
ECPublicKey keyPairPublicKey = keyPair.publicKey;
|
|
expect(keyPairPrivateKey.d.intValue(), equals(kPrivateKeyD));
|
|
expect(keyPairPublicKey.Q.x.toBigInteger().intValue(), equals(kPublicKeyQx));
|
|
expect(keyPairPublicKey.Q.y.toBigInteger().intValue(), equals(kPublicKeyQy));
|
|
});
|
|
|
|
test('serializeManifest adds key and content-hash', () {
|
|
AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
|
|
ECPublicKey keyPairPublicKey = keyPair.publicKey;
|
|
Uint8List manifestBytes = serializeManifest(kManifest, keyPairPublicKey, kTestBytes);
|
|
Map<String, dynamic> decodedManifest = JSON.decode(UTF8.decode(manifestBytes));
|
|
String expectedKey = BASE64.encode(keyPairPublicKey.Q.getEncoded());
|
|
expect(decodedManifest != null, equals(true));
|
|
expect(decodedManifest['name'], equals(kManifest['name']));
|
|
expect(decodedManifest['version'], equals(kManifest['version']));
|
|
expect(decodedManifest['key'], equals(expectedKey));
|
|
expect(decodedManifest['content-hash'], equals(kTestHash));
|
|
});
|
|
|
|
test('signManifest and verifyManifestSignature work', () {
|
|
AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
|
|
ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
|
|
ECPublicKey keyPairPublicKey = keyPair.publicKey;
|
|
Map<String, dynamic> manifest = JSON.decode(UTF8.decode(
|
|
serializeManifest(kManifest, keyPairPublicKey, kTestBytes))
|
|
);
|
|
Uint8List signatureBytes = signManifest(kTestBytes, keyPairPrivateKey);
|
|
|
|
bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes);
|
|
expect(verifies, equals(true));
|
|
|
|
// Ensure it fails with invalid signature or content.
|
|
Uint8List badBytes = new Uint8List.fromList(<int>[42]);
|
|
verifies = verifyManifestSignature(manifest, kTestBytes, badBytes);
|
|
expect(verifies, equals(false));
|
|
verifies = verifyManifestSignature(manifest, badBytes, signatureBytes);
|
|
expect(verifies, equals(false));
|
|
});
|
|
|
|
test('signing works with arbitrary key', () {
|
|
AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyGenerator.generateKeyPair();
|
|
ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
|
|
ECPublicKey keyPairPublicKey = keyPair.publicKey;
|
|
String failReason = 'offending private key: ${keyPairPrivateKey.d}';
|
|
Map<String, dynamic> manifest = JSON.decode(UTF8.decode(
|
|
serializeManifest(kManifest, keyPairPublicKey, kTestBytes))
|
|
);
|
|
Uint8List signatureBytes = signManifest(kTestBytes, keyPairPrivateKey);
|
|
|
|
bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes);
|
|
expect(verifies, equals(true), reason: failReason);
|
|
|
|
// Ensure it fails with invalid signature or content.
|
|
Uint8List badBytes = new Uint8List.fromList(<int>[42]);
|
|
verifies = verifyManifestSignature(manifest, kTestBytes, badBytes);
|
|
expect(verifies, equals(false), reason: failReason);
|
|
verifies = verifyManifestSignature(manifest, badBytes, signatureBytes);
|
|
expect(verifies, equals(false), reason: failReason);
|
|
});
|
|
|
|
test('verifyContentHash works', () async {
|
|
Stream<Uint8List> contentStream = new Stream<Uint8List>.fromIterable(kTestBytesList);
|
|
bool verifies = await verifyContentHash(new BigInteger(kTestHash), contentStream);
|
|
expect(verifies, equals(true));
|
|
|
|
// Ensure it fails with invalid hash or content.
|
|
contentStream = new Stream<Uint8List>.fromIterable(kTestBytesList);
|
|
verifies = await verifyContentHash(new BigInteger(0xdeadbeef), contentStream);
|
|
expect(verifies, equals(false));
|
|
|
|
Stream<Uint8List> badContentStream = new Stream<Uint8List>.fromIterable(
|
|
<Uint8List>[new Uint8List.fromList(<int>[42])]
|
|
);
|
|
verifies = await verifyContentHash(new BigInteger(kTestHash), badContentStream);
|
|
expect(verifies, equals(false));
|
|
});
|
|
}
|