dart-spectre/lib/src/spectre.dart

87 lines
2.2 KiB
Dart

import 'dart:convert';
import 'dart:typed_data';
import 'package:dart_spectre/src/scope.dart';
import 'package:dart_spectre/src/template.dart';
import "package:pointycastle/export.dart";
final scrypt = Scrypt();
final hmac = HMac(SHA256Digest(), 64);
class Spectre {
final String _name;
final String _secret;
late Scoper _scoper;
late Uint8List _key;
Spectre(this._name, this._secret, [Scoper? scoper]) {
_scoper = scoper ?? defaultScoper;
_key = _userKey();
}
Uint8List _userKey() {
var nameBytes = utf8.encode(_name);
var secretBytes = utf8.encode(_secret);
var keyScope = utf8.encode(_scoper.scope(Scope.authentication));
var nameBytesLen = nameBytes.length;
var keySalt = keyScope +
List.from([
nameBytesLen >> 24,
nameBytesLen >> 16,
nameBytesLen >> 8,
nameBytesLen,
]) +
nameBytes;
scrypt.init(ScryptParameters(32768, 8, 2, 64, Uint8List.fromList(keySalt)));
return scrypt.process(Uint8List.fromList(secretBytes));
}
Uint8List _siteKey(String name, int counter, Scope scope) {
var nameBytes = utf8.encode(name);
var scopeBytes = utf8.encode(_scoper.scope(scope));
var nameBytesLen = nameBytes.length;
var keySalt = scopeBytes +
List.from([
nameBytesLen >> 24,
nameBytesLen >> 16,
nameBytesLen >> 8,
nameBytesLen,
]) +
nameBytes +
List.from([
counter >> 24,
counter >> 16,
counter >> 8,
counter,
]);
hmac.init(KeyParameter(_key));
return hmac.process(Uint8List.fromList(keySalt));
}
String site(String siteName,
{Template? templateType,
int counter = 1,
Scope scope = Scope.authentication}) {
templateType = templateType ?? scopeDefaultTemplate(scope);
var siteKey = _siteKey(siteName, counter, scope);
var templateSet = templates[templateType]!;
var template = templateSet[siteKey[0] % templateSet.length];
var out = StringBuffer();
var idx = 0;
for (var rune in template.runes) {
var chars = characters[String.fromCharCode(rune)]!;
var char = chars[siteKey[++idx] % chars.length];
out.write(char);
}
return out.toString();
}
}