Ming Ke Ming (名可名) -- Account Module (Dart)
This document introduces a common Account Module for decentralized user identity authentication.
Meta
The Meta was generated by your private key, it can be used to build a new ID for entity, or verify the ID/PK pair.
It consists of 4 fields:
Field | Description |
---|---|
type | Algorithm Version |
key | Public Key |
seed | Entity Name (Optional) |
fingerprint | Signature to generate address (Optional) |
- if
seed
exists,fingerprint = privateKey.sign(seed)
; - if
seed
not exists,fingerprint = publicKey.data
.
Meta Type
MKM
(Default)BTC
Extended BTCETH
Extended ETH- ...
Meta Example
/* Meta(JsON) for hulk@4YeVEN3aUnvC1DNUufCq1bs9zoBSJTzVEj */
{
"type" : 0x01,
"key" : {
"algorithm" : "RSA",
"data" : "-----BEGIN PUBLIC KEY-----\nMIGJAoGBALB+vbUK48UU9rjlgnohQowME+3JtTb2hLPqtatVOW364/EKFq0/PSdnZVE9V2Zq+pbX7dj3nCS4pWnYf40ELH8wuDm0Tc4jQ70v4LgAcdy3JGTnWUGiCsY+0Z8kNzRkm3FJid592FL7ryzfvIzB9bjg8U2JqlyCVAyUYEnKv4lDAgMBAAE=\n-----END PUBLIC KEY-----",
"mode" : "ECB",
"padding" : "PKCS1",
"digest" : "SHA256"
},
"seed" : "hulk",
"fingerprint" : "jIPGWpWSbR/DQH6ol3t9DSFkYroVHQDvtbJErmFztMUP2DgRrRSNWuoKY5Y26qL38wfXJQXjYiWqNWKQmQe/gK8M8NkU7lRwm+2nh9wSBYV6Q4WXsCboKbnM0+HVn9Vdfp21hMMGrxTX1pBPRbi0567ZjNQC8ffdW2WvQSoec2I="
}
ID
The ID is used to identify an entity(user/group). It consists of 3 fields:
Field | Description |
---|---|
type | Entity type |
name | Same with meta.seed (Optional) |
address | Unique Identification |
terminal | Login point (Optional) |
The ID format is name@address[/terminal]
.
# ID examples
ID1 = "hulk@4YeVEN3aUnvC1DNUufCq1bs9zoBSJTzVEj"; // Immortal Hulk
ID2 = "moki@4WDfe3zZ4T7opFSi3iDAKiuTnUHjxmXekk"; // Monkey King
ID Name
The Name field is a username, or just a random string for group:
- The length of name must more than 1 byte, less than 32 bytes;
- It should be composed by a-z, A-Z, 0-9, or charactors '_', '-', '.';
- It cannot contain key charactors('@', '/').
# Name examples
user_name = "Albert.Moky";
group_name = "Group-9527";
It's equivalent to meta.seed
ID Address
The Address field was created with the Meta and a Network ID:
import 'dart:typed_data';
import 'package:mkm/type.dart';
import 'package:mkm/digest.dart';
import 'package:mkm/format.dart';
import 'package:mkm/mkm.dart';
/// Address like BitCoin
/// ~~~~~~~~~~~~~~~~~~~~
///
/// data format: "network+digest+code"
/// network -- 1 byte
/// digest -- 20 bytes
/// check code -- 4 bytes
///
/// algorithm:
/// fingerprint = PK.data
/// digest = ripemd160(sha256(fingerprint));
/// code = sha256(sha256(network + digest)).prefix(4);
/// address = base58_encode(network + digest + code);
///
class BTCAddress extends ConstantString implements Address {
BTCAddress(super.string, int network) : _type = network;
final int _type;
@override
int get network => _type;
/// Generate BTC address with fingerprint and network ID
///
/// @param fingerprint - meta.fingerprint or key.data
/// @param network - address type
/// @return Address object
static BTCAddress generate(Uint8List fingerprint, int network) {
// 1. digest = ripemd160(sha256(fingerprint))
Uint8List digest = RIPEMD160.digest(SHA256.digest(fingerprint));
// 2. head = network + digest
BytesBuilder bb = BytesBuilder(copy: false);
bb.addByte(network);
bb.add(digest);
Uint8List head = bb.toBytes();
// 3. cc = sha256(sha256(head)).prefix(4)
Uint8List cc = _checkCode(head);
// 4. data = base58_encode(head + cc)
bb = BytesBuilder(copy: false);
bb.add(head);
bb.add(cc);
return BTCAddress(Base58.encode(bb.toBytes()), network);
}
/// Parse a string for BTC address
///
/// @param address - address string
/// @return null on error
static BTCAddress? parse(String address) {
if (address.length < 26 || address.length > 35) {
return null;
}
// decode
Uint8List? data = Base58.decode(address);
if (data == null || data.length != 25) {
return null;
}
// check code
Uint8List prefix = data.sublist(0, 21);
Uint8List suffix = data.sublist(21, 25);
Uint8List cc = _checkCode(prefix);
if (Arrays.equals(cc, suffix)) {
return BTCAddress(address, data[0]);
} else {
return null;
}
}
}
Uint8List _checkCode(Uint8List data) {
return SHA256.digest(SHA256.digest(data)).sublist(0, 4);
}
When you get a meta for the entity ID from the network, you must verify it with the consensus algorithm before accepting its public key.
(All data encode with BASE64 algorithm as default, excepts the address)