blob: f45770013c08acaa5aa602b0d1eddf195b7a17c4 [file] [edit]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test vectors are sourced from Project Wycheproof
// (https://github.com/C2SP/wycheproof).
// Copyright 2017-2026 Google LLC / C2SP.
// Licensed under the Apache License, Version 2.0.
// See third_party/wycheproof/LICENSE for full license text.
/// Downloads HMAC test vectors from Project Wycheproof
/// (https://github.com/C2SP/wycheproof) and generates
/// `test/wycheproof_data.dart`.
library;
import 'dart:convert';
import 'dart:io';
final _baseUrl = Uri.https(
'raw.githubusercontent.com',
'C2SP/wycheproof/main/testvectors_v1/',
);
const _hmacVectors = [
'hmac_sha256_test.json',
'hmac_sha512_test.json',
'hmac_sha384_test.json',
'hmac_sha224_test.json',
'hmac_sha512_224_test.json',
'hmac_sha512_256_test.json',
'hmac_sha1_test.json',
];
Future<void> main() async {
final client = HttpClient();
final vectorContents = <String, String>{};
for (final file in _hmacVectors) {
final uri = _baseUrl.resolve(file);
stdout.write('Fetching $file from $_baseUrl... ');
final request = await client.getUrl(uri);
final response = await request.close();
if (response.statusCode != 200) {
stderr.writeln('FAILED (${response.statusCode})');
exitCode = 1;
continue;
}
final content = await response.transform(utf8.decoder).join();
vectorContents[file] = content;
stdout.writeln('DONE (${(content.length / 1024).toStringAsFixed(1)} KB)');
}
client.close();
// Generate test/wycheproof_data.dart with wrapped base64-encoded strings
// (chunked at 70 chars) matching the pubviz asset-inlining pattern.
final buffer = StringBuffer()
..writeln('// Test vectors are sourced from Project Wycheproof '
'(https://github.com/C2SP/wycheproof).')
..writeln('// Copyright 2017-2026 Google LLC / C2SP.')
..writeln('// Licensed under the Apache License, Version 2.0.')
..writeln('// See third_party/wycheproof/LICENSE for full license text.')
..writeln()
..writeln('// GENERATED CODE - DO NOT MODIFY BY HAND')
..writeln('// Generated by tool/pull_wycheproof.dart')
..writeln()
..writeln('// ignore_for_file: lines_longer_than_80_chars')
..writeln()
..writeln('const wycheproofVectorsBase64 = <String, String>{');
for (final entry in vectorContents.entries) {
final base64String = base64.encode(utf8.encode(entry.value));
buffer.writeln(" '${entry.key}':");
const chunkSize = 70;
for (var i = 0; i < base64String.length; i += chunkSize) {
final end = (i + chunkSize < base64String.length)
? i + chunkSize
: base64String.length;
final chunk = base64String.substring(i, end);
final isLast = end == base64String.length;
buffer.writeln(" '$chunk'${isLast ? ',' : ''}");
}
}
buffer.writeln('};');
final targetFile = File('test/wycheproof_data.dart');
await targetFile.writeAsString(buffer.toString());
stdout.writeln(
'Generated ${targetFile.path} '
'(${(buffer.length / 1024).toStringAsFixed(1)} KB)',
);
final formatResult = await Process.run(
Platform.executable,
['format', targetFile.path],
);
if (formatResult.exitCode != 0) {
stderr
.writeln('Error formatting ${targetFile.path}: ${formatResult.stderr}');
}
}