Merge branch 'master' of https://github.com/pointbiz/bitaddress.org
Conflicts: bitaddress.org.html src/bitaddress-ui.html src/ninja.translator.js
This commit is contained in:
commit
d56c505885
10 changed files with 2152 additions and 173 deletions
|
@ -24,6 +24,7 @@ module.exports = function (grunt) {
|
|||
{ token: "//cryptojs.ripemd160.js", file: "./src/cryptojs.ripemd160.js" },
|
||||
{ token: "//crypto-scrypt.js", file: "./src/crypto-scrypt.js" },
|
||||
{ token: "//ellipticcurve.js", file: "./src/ellipticcurve.js" },
|
||||
{ token: "//secrets.js", file: "./src/secrets.js" },
|
||||
{ token: "//ninja.key.js", file: "./src/ninja.key.js" },
|
||||
{ token: "//ninja.misc.js", file: "./src/ninja.misc.js" },
|
||||
{ token: "//ninja.onload.js", file: "./src/ninja.onload.js" },
|
||||
|
@ -34,6 +35,7 @@ module.exports = function (grunt) {
|
|||
{ token: "//ninja.bulkwallet.js", file: "./src/ninja.bulkwallet.js" },
|
||||
{ token: "//ninja.brainwallet.js", file: "./src/ninja.brainwallet.js" },
|
||||
{ token: "//ninja.vanitywallet.js", file: "./src/ninja.vanitywallet.js" },
|
||||
{ token: "//ninja.splitwallet.js", file: "./src/ninja.splitwallet.js" },
|
||||
{ token: "//ninja.detailwallet.js", file: "./src/ninja.detailwallet.js" },
|
||||
{ token: "//qrcode.js", file: "./src/qrcode.js" },
|
||||
{ token: "//securerandom.js", file: "./src/securerandom.js" },
|
||||
|
|
1128
bitaddress.org.html
1128
bitaddress.org.html
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bitaddress.org",
|
||||
"version": "2.8.1",
|
||||
"version": "2.9.3",
|
||||
"description": "Open Source JavaScript Client-Side Bitcoin Wallet Generator",
|
||||
"main": "Gruntfile.js",
|
||||
"dependencies": {
|
||||
|
|
File diff suppressed because one or more lines are too long
73
src/main.css
73
src/main.css
|
@ -1,10 +1,10 @@
|
|||
.more { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDEvMDIvMTLltnQyAAAB1UlEQVQ4jYWTS04bQRCGv3q0x8gMYJCwknCGLDgLVwiH4grhLFaUXdhkQ0A8pBg/FOLpnmbhMYzxRKlNS1Vdf/31V5XknGnb+eXJCBjzbzu9OLu+azu845Opysej4wHmshF4uJ2TUrb3CV0gIBAKRboC5C2vdkDE9fdty6/xDegvXz+NgDbFUejZ+PjDgExmtpxS9vYwMe5u5iyX8RRoa5Ic+C4qx9KUN1MGu4E618yqJ5axAp44KA7ZL3eYzp/HKdVIw7WK8d6BuDvcod9TQlBEIOXEdPlElSoUJabIIs4Z7h9yNDwgqOMayLXw7epHVIBggrsgspZPUBQyiCgugRQji7TAVDF1XB2TlQoOYCqovkmpopS9fcoiM3ue0rOCYf8IU8NklWxiiOQ3EPXtWagIqo6KYWYEc4IGvMViA6RrnCJKVS9B8ypRHG1YKNa0Ur+C+MPt/I2BKWVZUO4FgvQ47PcptEDF+T2Z8TiZUMWIyGtpd+Bze5VTSqP57O/4YG+AN/RXbSiPkwmL5z/be/L+mM4vT2JKeUW7EXD1erMz/Lo4u77f0K9DDhdA1XG11jh9vWBb99Z9gAg5QZ2hzpmUa0RSW4f/gqSY0s3Vz+tufEjvHS8Tg6BXC7qVbQAAAABJRU5ErkJggg==)
|
||||
no-repeat left center; width: 17px; height: 17px; display: inline-block; float: right; }
|
||||
no-repeat left center; width: 17px; height: 17px; display: inline-block; float: right; cursor: pointer; }
|
||||
.less { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDEvMDIvMTLltnQyAAABuklEQVQ4ja2US25TQRBFT336OSEY5ESyBfEakNiLt0AW5S2QvQQxAiZIYBwSz/yByH7dxcB2bPMME+hJS/W5fetWVUtE8K/HfzdcXfdfqsr4onuGuRz4Jrdzcg6Gg9HfQYAxAqmlSMMlQJO5/oliE4AtQLcR++btZQ+wPVsvVXbTfXFGEMyWU9rVM0yMu/Gc5bJ+DdztxWcH3otKVzbPmyq5LnwfzSgEBMxlhqJEBFWVKKUgG66rur53oH7aOeWkUlJSRCBHZracssorlLXttHpCpzonaYukjmsiivDu08daAZIJ7oLIVg9BUQgQUVwSua5Z5AWmiqnj6pisVXAAU0F1J6WK0q6e024Fs4cplbXonFxgapisk00MkdiBqDd7oSKoOiqGmZHMSZrwPRYHIMfaKaKsyhI01oni6IaFYptSyiOIT27nOwaq5FyQrUAIC/nBhK+UErRSos55z4878CrneJyTnHOvquymf3mOb+hvy/jw+QuLh5/NORkORvsGrq77dc6xpr0RcH07y3oF8G04GN0f6HdEDhdA1XG1vXb6dsAa+3Z8AREiQwkoEeQoiBzocHDkf/wnvwC5IpRVsUDNUgAAAABJRU5ErkJggg==)
|
||||
no-repeat left center; width: 17px; height: 17px; display: inline-block; float: right; }
|
||||
a { position: relative; z-index: 20; }
|
||||
.right { text-align: right; }
|
||||
.walletarea { display: none; border: 2px solid green; }
|
||||
.walletarea { display: none; border: 2px solid #009900; }
|
||||
hr { margin: 20px 0; border-top: 2px dashed #008000; }
|
||||
.keyarea { height: 110px; text-align: left; position: relative; padding: 5px; }
|
||||
.keyarea .public { float: left; }
|
||||
|
@ -16,18 +16,20 @@ hr { margin: 20px 0; border-top: 2px dashed #008000; }
|
|||
.keyarea .qrcode_private { display: inline-block; position: relative; top: 28px; float: right; }
|
||||
.pubkeyhex { word-wrap: break-word; }
|
||||
body { font-family: Arial; }
|
||||
body, html { min-height: 99%; }
|
||||
.faqs ol { padding: 0 0 0 25px; }
|
||||
.faqs li { padding: 3px 0; }
|
||||
.question { padding: 10px 15px; text-align: left; cursor: pointer; }
|
||||
.question:hover, .expandable:hover { color: #77777A; }
|
||||
.answer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; }
|
||||
.faq { border: 0; border-top: 2px solid green; }
|
||||
.faq { border: 0; border-top: 2px solid #009900; }
|
||||
|
||||
#wallets { clear: both; }
|
||||
#btcaddress, #btcprivwif, #detailaddress, #detailaddresscomp, #detailprivwif, #detailprivwifcomp { font-family: monospace; font-size: 1.25em; }
|
||||
#seedpoolarea { display: none; }
|
||||
#seedpooldisplay { font-family: monospace; font-size: 1em; width: 640px; padding: 15px 5px; word-wrap: break-word; }
|
||||
.seedpoint { width: 6px; height: 6px; display: block; border-radius: 3px; background-color: green; position: absolute; z-index: 10; }
|
||||
#generate { font-family: monospace; font-size: 1.25em; height: 305px; text-align: left; position: relative; padding: 5px; border: 2px solid green; }
|
||||
.seedpoint { width: 6px; height: 6px; display: block; border-radius: 3px; background-color: #009900; position: absolute; z-index: 10; }
|
||||
#generate { font-family: monospace; font-size: 1.25em; height: 305px; text-align: left; position: relative; padding: 5px; border: 2px solid #009900; clear: both; }
|
||||
#generate span { padding: 5px 5px 0 5px; }
|
||||
#generatekeyinput { position: relative; z-index: 20; }
|
||||
#keyarea { height: 250px; }
|
||||
|
@ -40,14 +42,14 @@ body { font-family: Arial; }
|
|||
#keyarea .public { width: 30%; display: table-cell; }
|
||||
#singlearea { font-size: 90%; }
|
||||
#singlesecret { position: relative; top: -130px; float: right; right: 200px; color: red; font-weight: bolder; font-size: 200%; }
|
||||
#singleshare { position: relative; top: -110px; float: left; left: 160px; color: green; font-weight: bolder; font-size: 200%; }
|
||||
#singlesafety { text-align: left; padding: 5px; border-top: 2px solid green; top: -25px; position: relative; }
|
||||
#singleshare { position: relative; top: -110px; float: left; left: 160px; color: #009900; font-weight: bolder; font-size: 200%; }
|
||||
#singlesafety { text-align: left; padding: 5px; border-top: 2px solid #009900; top: -25px; position: relative; }
|
||||
|
||||
#main { position: relative; text-align: center; margin: 0px auto; width: 1005px; }
|
||||
#main { position: relative; text-align: center; margin: 0px auto; width: 808px; }
|
||||
#logo { width: 578px; height: 80px; }
|
||||
|
||||
#paperarea { min-height: 120px; display: none; }
|
||||
#paperarea .keyarea { border: 2px solid green; border-top: 0; }
|
||||
#paperarea .keyarea { border: 2px solid #009900; border-top: 0; }
|
||||
#paperarea .keyarea.art { display: block; height: auto; border: 0; font-family: Ubuntu, Arial; padding: 0; margin: 0; }
|
||||
#paperarea .artwallet .papersvg { width: 486px; height: 261px; border: 0; margin: 0; padding: 0; left: 0; }
|
||||
#paperarea .artwallet .qrcode_public { top: 52px; left: 17px; z-index: 100; margin: 0; float: none; display: block; position: absolute; background-color: #FFFFFF;
|
||||
|
@ -111,12 +113,24 @@ body { font-family: Arial; }
|
|||
#vanityarea .label { text-decoration: underline; }
|
||||
#vanityarea .output { font-family: monospace; font-size: 1.25em; display: block; }
|
||||
#vanityarea .notes { text-align: left; font-size: 80%; padding: 0 0 20px 0; }
|
||||
#vanitystep1area { display: none; text-align: left; position: relative; padding: 15px; border-bottom: 2px solid green; }
|
||||
#vanitystep1area { display: none; text-align: left; position: relative; padding: 15px; border-bottom: 2px solid #009900; }
|
||||
#vanitystep1label { padding-left: 5px; }
|
||||
#vanitystep2area { border-top: 2px solid green; display: block; padding: 15px; }
|
||||
#vanitystep2area { border-top: 2px solid #009900; display: block; padding: 15px; }
|
||||
#vanitystep2inputs { padding: 0 15px 10px 15px; }
|
||||
#vanitycalc { margin-top: 5px; }
|
||||
|
||||
#splitarea { text-align: left; }
|
||||
#splitarea span { padding: 0; }
|
||||
#splitcommands { padding: 10px 15px; text-align: left; }
|
||||
#combinecommands { padding: 10px 15px; }
|
||||
#splitstep1area { display: none; text-align: left; position: relative; padding: 0; border-bottom: 2px solid #009900; }
|
||||
.splitsharerow { border-bottom: 2px solid #009900; padding: 15px; }
|
||||
.splitsharerow:last-child { border-bottom: 0; }
|
||||
#combinelabelprivatekey { text-decoration: underline; }
|
||||
#splitarea .output { display: block; font-family: monospace; font-size: 1.25em; }
|
||||
#splitarea span.output { display: inline; }
|
||||
#splitstep2area { padding: 10px 15px; }
|
||||
|
||||
.englishjson { text-align: center; padding: 40px 0 20px 0; }
|
||||
.unittests { text-align: center; }
|
||||
.unittests div { width: 894px; font-family: monospace; text-align: left; margin: auto; padding: 5px; border: 1px solid black; }
|
||||
|
@ -134,14 +148,31 @@ body { font-family: Arial; }
|
|||
@media screen
|
||||
{
|
||||
#tagline { margin: 0 0 15px 0; font-style: italic; }
|
||||
.menu { text-align: left; }
|
||||
.menu .tab { border-top-left-radius: 5px; border-top-right-radius: 5px; display: inline-block; background-color: #6C8C6C;
|
||||
border: 2px solid green; padding: 5px; margin: 0 2px 0 0; position: relative; top: 2px; z-index: 110; cursor: pointer; }
|
||||
.menu .tab:hover { color: #FFF; }
|
||||
.menu .tab.selected { background-color: #FFF; border-bottom: 2px solid #FFF; cursor: default; }
|
||||
.menu
|
||||
{
|
||||
text-align: left; margin: 0; padding: 0; display: block;
|
||||
background-color: #009900; /* # 009900 # 53c100 */
|
||||
border-top-left-radius: 5px; border-top-right-radius: 5px;
|
||||
}
|
||||
.menu .tab
|
||||
{
|
||||
position: relative; display: inline-block; border: 0px solid red;
|
||||
margin: 0; list-style: none; z-index: 110; cursor: pointer;
|
||||
top: 1px; padding: 10px 20px; width: 162px; text-align: center;
|
||||
}
|
||||
.menu .tab.selected
|
||||
{
|
||||
cursor: default;
|
||||
background-color: #FFF; margin: 6px 16px; padding: 4px; border-radius: 5px;
|
||||
}
|
||||
.menu .tab:hover
|
||||
{
|
||||
background-color: #FFF; margin: 6px 16px; padding: 4px; border-radius: 5px;
|
||||
}
|
||||
.menu .tab.selected:hover { color: #000; }
|
||||
.pagebreak { height: 50px; }
|
||||
.commands { border-bottom: 2px solid green; padding: 10px 2px; margin-bottom: 0; }
|
||||
|
||||
.pagebreak { height: 50px; }
|
||||
.commands { border-bottom: 2px solid #009900; padding: 10px 2px; margin-bottom: 0; }
|
||||
.commands .row { padding: 0 0; text-align: left; }
|
||||
.commands .row.extra { padding-top: 6px; }
|
||||
.commands span { padding: 0 10px; }
|
||||
|
@ -150,7 +181,7 @@ body { font-family: Arial; }
|
|||
.expandable { padding: 10px 15px; text-align: left; cursor: pointer; }
|
||||
|
||||
#menu { visibility: hidden; font-size: 90%; }
|
||||
#culturemenu { text-align: right; padding: 0 20px; }
|
||||
#culturemenu { text-align: right; padding: 0 20px; margin-bottom: 3px; }
|
||||
#culturemenu span { padding: 3px; }
|
||||
#culturemenu .selected { text-decoration: none; color: #000000; }
|
||||
|
||||
|
@ -163,7 +194,7 @@ body { font-family: Arial; }
|
|||
#detailcommands span { padding: 0 10px; }
|
||||
#detailprivkey { width: 250px; }
|
||||
#detailprivkeypassphrase { width: 250px; }
|
||||
.paper .commands { border: 2px solid green; }
|
||||
.paper .commands { border: 2px solid #009900; }
|
||||
#bulkstartindex, #paperlimit, #paperlimitperpage { width: 35px; }
|
||||
#bulklimit { width: 45px; }
|
||||
|
||||
|
@ -182,7 +213,7 @@ body { font-family: Arial; }
|
|||
#main { width: auto; }
|
||||
#singlearea { border: 0; }
|
||||
#singlesafety { border: 0; }
|
||||
#paperarea .keyarea:first-child { border-top: 2px solid green; }
|
||||
#paperarea .keyarea:first-child { border-top: 2px solid #009900; }
|
||||
#paperarea .keyarea.art:first-child { border: 0; }
|
||||
.pagebreak { height: 1px; }
|
||||
.paper #logo { display: none; }
|
||||
|
|
|
@ -10,6 +10,8 @@ if (ninja.getQueryString()["asyncunittests"] == "true" || ninja.getQueryString()
|
|||
// change language
|
||||
if (ninja.getQueryString()["culture"] != undefined) {
|
||||
ninja.translator.translate(ninja.getQueryString()["culture"]);
|
||||
} else {
|
||||
ninja.translator.autoDetectTranslation();
|
||||
}
|
||||
// testnet, check if testnet edition should be activated
|
||||
if (ninja.getQueryString()["testnet"] == "true" || ninja.getQueryString()["testnet"] == "1") {
|
||||
|
|
113
src/ninja.splitwallet.js
Normal file
113
src/ninja.splitwallet.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
ninja.wallets.splitwallet = {
|
||||
open: function () {
|
||||
document.getElementById("splitarea").style.display = "block";
|
||||
secrets.setRNG();
|
||||
secrets.init(7); // 7 bits allows for up to 127 shares
|
||||
},
|
||||
|
||||
close: function () {
|
||||
document.getElementById("splitarea").style.display = "none";
|
||||
},
|
||||
|
||||
mkOutputRow: function (s, id, lbltxt) {
|
||||
var row = document.createElement("div");
|
||||
var label = document.createElement("label");
|
||||
label.innerHTML = lbltxt;
|
||||
var qr = document.createElement("div");
|
||||
var output = document.createElement("span");
|
||||
output.setAttribute("class", "output");
|
||||
output.innerHTML = s;
|
||||
|
||||
qr.setAttribute("id", id);
|
||||
row.setAttribute("class", "splitsharerow");
|
||||
row.appendChild(label);
|
||||
row.appendChild(output);
|
||||
row.appendChild(qr);
|
||||
row.appendChild(document.createElement("br"));
|
||||
|
||||
return row;
|
||||
},
|
||||
|
||||
stripLeadZeros: function (hex) { return hex.split(/^0+/).slice(-1)[0]; },
|
||||
|
||||
hexToBytes: function (hex) {
|
||||
//if input has odd number of digits, pad it
|
||||
if (hex.length % 2 == 1)
|
||||
hex = "0" + hex;
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Split a private key and update information in the HTML
|
||||
splitKey: function () {
|
||||
try {
|
||||
var numshares = parseInt(document.getElementById('splitshares').value);
|
||||
var threshold = parseInt(document.getElementById('splitthreshold').value);
|
||||
var key = new Bitcoin.ECKey(false);
|
||||
var bitcoinAddress = key.getBitcoinAddress();
|
||||
var shares = ninja.wallets.splitwallet.getFormattedShares(key.getBitcoinHexFormat(), numshares, threshold);
|
||||
|
||||
var output = document.createElement("div");
|
||||
output.setAttribute("id", "splitoutput");
|
||||
var m = {};
|
||||
output.appendChild(this.mkOutputRow(bitcoinAddress, "split_addr", "Bitcoin Address: "));
|
||||
m["split_addr"] = bitcoinAddress;
|
||||
|
||||
for (var i = 0; i < shares.length; i++) {
|
||||
var id = "split_qr_" + i;
|
||||
output.appendChild(this.mkOutputRow(shares[i], id, "Share " + (i + 1) + ": "));
|
||||
m[id] = shares[i];
|
||||
}
|
||||
|
||||
document.getElementById("splitstep1area").innerHTML = output.innerHTML;
|
||||
ninja.qrCode.showQrCode(m);
|
||||
|
||||
document.getElementById("splitstep1area").style.display = "block";
|
||||
document.getElementById("splitstep1icon").setAttribute("class", "less");
|
||||
}
|
||||
catch (e) {
|
||||
// browser does not have sufficient JavaScript support to generate a bitcoin address
|
||||
alert(e);
|
||||
}
|
||||
},
|
||||
|
||||
// Combine shares of a private key to retrieve the key
|
||||
combineShares: function () {
|
||||
try {
|
||||
document.getElementById("combinedprivatekey").innerHTML = "";
|
||||
var shares = document.getElementById("combineinput").value.trim().split(/\W+/);
|
||||
var combinedBytes = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var privkeyBase58 = new Bitcoin.ECKey(combinedBytes).getBitcoinWalletImportFormat();
|
||||
document.getElementById("combinedprivatekey").innerHTML = privkeyBase58;
|
||||
}
|
||||
catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
},
|
||||
|
||||
// generate shares and format them in base58
|
||||
getFormattedShares: function (key, numshares, threshold) {
|
||||
var shares = secrets.share(key, numshares, threshold).map(ninja.wallets.splitwallet.hexToBytes).map(Bitcoin.Base58.encode);
|
||||
return shares;
|
||||
},
|
||||
|
||||
// combine base58 formatted shares and return a bitcoin byte array
|
||||
combineFormattedShares: function (shares) {
|
||||
var combined = secrets.combine(shares.map(Bitcoin.Base58.decode).map(Crypto.util.bytesToHex).map(ninja.wallets.splitwallet.stripLeadZeros));
|
||||
return ninja.wallets.splitwallet.hexToBytes(combined);
|
||||
},
|
||||
|
||||
openCloseStep: function (num) {
|
||||
// do close
|
||||
if (document.getElementById("splitstep" + num + "area").style.display == "block") {
|
||||
document.getElementById("splitstep" + num + "area").style.display = "none";
|
||||
document.getElementById("splitstep" + num + "icon").setAttribute("class", "more");
|
||||
}
|
||||
// do open
|
||||
else {
|
||||
document.getElementById("splitstep" + num + "area").style.display = "block";
|
||||
document.getElementById("splitstep" + num + "icon").setAttribute("class", "less");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,6 +1,17 @@
|
|||
ninja.translator = {
|
||||
currentCulture: "en",
|
||||
|
||||
autoDetectTranslation: function() {
|
||||
// window.navigator.language for Firefox / Chrome / Opera Safari
|
||||
// window.navigator.userLanguage for IE
|
||||
var language = window.navigator.language || window.navigator.userLanguage;
|
||||
if (!ninja.translator.translate(language)) {
|
||||
// Try to remove part after dash, for example cs-CZ -> cs
|
||||
language = language.substr(0, language.indexOf('-'));
|
||||
ninja.translator.translate(language);
|
||||
}
|
||||
},
|
||||
|
||||
translate: function (culture) {
|
||||
var dict = ninja.translator.translations[culture];
|
||||
if (dict) {
|
||||
|
@ -20,6 +31,9 @@ ninja.translator = {
|
|||
document.getElementById(id).innerHTML = dict[id];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -101,7 +115,9 @@ ninja.translator = {
|
|||
"singletip2": "<b>To safeguard this wallet</b> you must print or otherwise record the Bitcoin address and private key. It is important to make a backup copy of the private key and store it in a safe location. This site does not have knowledge of your private key. If you are familiar with PGP you can download this all-in-one HTML page and check that you have an authentic version from the author of this site by matching the SHA1 hash of this HTML with the SHA1 hash available in the signed version history document linked on the footer of this site. If you leave/refresh the site or press the Generate New Address button then a new private key will be generated and the previously displayed private key will not be retrievable. Your Bitcoin private key should be kept a secret. Whomever you share the private key with has access to spend all the bitcoins associated with that address. If you print your wallet then store it in a zip lock bag to keep it safe from water. Treat a paper wallet like cash.", //TODO: please translate
|
||||
"singletip3": "<b>Add funds</b> to this wallet by instructing others to send bitcoins to your Bitcoin address.", //TODO: please translate
|
||||
"singletip4": "<b>Check your balance</b> by going to blockchain.info or blockexplorer.com and entering your Bitcoin address.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info or mtgox.com and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singleshare": "SHARE", //TODO: please translate
|
||||
"singlesecret": "SECRET", //TODO: please translate
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "Ocultar diseño",
|
||||
|
@ -235,7 +251,10 @@ ninja.translator = {
|
|||
"singletip2": "<b>To safeguard this wallet</b> you must print or otherwise record the Bitcoin address and private key. It is important to make a backup copy of the private key and store it in a safe location. This site does not have knowledge of your private key. If you are familiar with PGP you can download this all-in-one HTML page and check that you have an authentic version from the author of this site by matching the SHA1 hash of this HTML with the SHA1 hash available in the signed version history document linked on the footer of this site. If you leave/refresh the site or press the Generate New Address button then a new private key will be generated and the previously displayed private key will not be retrievable. Your Bitcoin private key should be kept a secret. Whomever you share the private key with has access to spend all the bitcoins associated with that address. If you print your wallet then store it in a zip lock bag to keep it safe from water. Treat a paper wallet like cash.", //TODO: please translate
|
||||
"singletip3": "<b>Add funds</b> to this wallet by instructing others to send bitcoins to your Bitcoin address.", //TODO: please translate
|
||||
"singletip4": "<b>Check your balance</b> by going to blockchain.info or blockexplorer.com and entering your Bitcoin address.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info or mtgox.com and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singleshare": "SHARE", //TODO: please translate
|
||||
"singlesecret": "SECRET", //TODO: please translate
|
||||
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "Retirer Le Style?",
|
||||
|
@ -369,7 +388,9 @@ ninja.translator = {
|
|||
"singletip2": "<b>To safeguard this wallet</b> you must print or otherwise record the Bitcoin address and private key. It is important to make a backup copy of the private key and store it in a safe location. This site does not have knowledge of your private key. If you are familiar with PGP you can download this all-in-one HTML page and check that you have an authentic version from the author of this site by matching the SHA1 hash of this HTML with the SHA1 hash available in the signed version history document linked on the footer of this site. If you leave/refresh the site or press the Generate New Address button then a new private key will be generated and the previously displayed private key will not be retrievable. Your Bitcoin private key should be kept a secret. Whomever you share the private key with has access to spend all the bitcoins associated with that address. If you print your wallet then store it in a zip lock bag to keep it safe from water. Treat a paper wallet like cash.", //TODO: please translate
|
||||
"singletip3": "<b>Add funds</b> to this wallet by instructing others to send bitcoins to your Bitcoin address.", //TODO: please translate
|
||||
"singletip4": "<b>Check your balance</b> by going to blockchain.info or blockexplorer.com and entering your Bitcoin address.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info or mtgox.com and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singletip5": "<b>Spend your bitcoins</b> by going to blockchain.info and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.", //TODO: please translate
|
||||
"singleshare": "SHARE", //TODO: please translate
|
||||
"singlesecret": "SECRET", //TODO: please translate
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "Απόκρυψη γραφικού;",
|
||||
|
@ -503,7 +524,9 @@ ninja.translator = {
|
|||
"singletip2": "<b>Per mettere in sicurezza questo portafogli</b> devi stampare o quantomeno salvare l'indirizzo bitcoin e la Chiave privata. È molto importante fare una copia di backup della chiave privata e conservarla in un posto sicuro. Questo sito non conosce la tua chiave privata. Se hai familiarità con PGP, puoi scaricare per intero questa pagina HTML e controllare la sua autentiticità. Puoi confrontare il codice SHA1 della pagina scaricata con il codice firmato dall'autore che trovi nella cronologia delle versioni (in fondo alla pagina). Se abbandoni/aggiorni la pagina web oppure premi il tasto Genera, un nuovo indirizzo sostituirà quello vecchio che non potrà più essere recuperato. La chiave privata dovrebbe essere tenuta segreta, chiunque conosca la chiave privata può avere accesso e spendere i tuoi bitcoin. Se stampi il tuo portafogli conservalo in una busta di plastica sigillata per tenerla al riparo dall'acqua. Tratta quanto stampato alla stregua di una banconota.",
|
||||
"singletip3": "<b>Ricevi fondi</b> su questo portafogli mostrando l'indirizzo bitcoin per il versamento.",
|
||||
"singletip4": "<b>Controlla il saldo</b> visitando blockchain.info o blockexplorer.com cercando il tuo indirizzo bitcoin.",
|
||||
"singletip5": "<b>Spendi i tuoi bitcoin</b> aprendo un account su blockchain.info o mtgox.com usando la chiave privata. Puoi anche spendere i tuoi bitcoin scaricando il popolare client p2p ed importando in esso il portafogli. Tieni presente che quando importi una chiave nel client p2p, nel momento in cui spendi le monete, la chiave viene raggruppata insieme alle altre presenti nel programma con i restanti bitcoin. Quando esegui una transazione gli spiccioli verranno invitati verso un altro indirizzo all'interno del tuo portafogli gestito dal client p2p. Quindi dovresti tenere un backup del portafogli contenuto nel client p2p e tenere questo in un posto sicuro fin tanto terrai dei bitcoin lì. Satoshi consiglia di non cancellare mai un portafogli. ",
|
||||
"singletip5": "<b>Spendi i tuoi bitcoin</b> aprendo un account su blockchain.info usando la chiave privata. Puoi anche spendere i tuoi bitcoin scaricando il popolare client p2p ed importando in esso il portafogli. Tieni presente che quando importi una chiave nel client p2p, nel momento in cui spendi le monete, la chiave viene raggruppata insieme alle altre presenti nel programma con i restanti bitcoin. Quando esegui una transazione gli spiccioli verranno invitati verso un altro indirizzo all'interno del tuo portafogli gestito dal client p2p. Quindi dovresti tenere un backup del portafogli contenuto nel client p2p e tenere questo in un posto sicuro fin tanto terrai dei bitcoin lì. Satoshi consiglia di non cancellare mai un portafogli. ",
|
||||
"singleshare": "SHARE", //TODO: please translate
|
||||
"singlesecret": "SECRET", //TODO: please translate
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "Senza grafica?",
|
||||
|
@ -513,7 +536,6 @@ ninja.translator = {
|
|||
"paperprint": "Stampa",
|
||||
"paperlabelBIPpassphrase": "Passphrase:",
|
||||
"paperlabelencrypt": "BIP38 criptato?",
|
||||
"paperadvancedcommandslabel": "Opzioni avanzate",
|
||||
|
||||
// bulk wallet html
|
||||
"bulklabelstartindex": "Indice iniziale:",
|
||||
|
@ -638,7 +660,9 @@ ninja.translator = {
|
|||
"singletip2": "<b>Um dieses Wallet zu schützen,</b> musst du es entweder ausdrucken oder anderweitig die Bitcoin-Adresse und den privaten Schlüssel sichern. Fertige auf jeden Fall eine Kopie des privaten Schlüssels an und bewahre sie an einem sicheren Ort auf. Der private Schlüssel liegt nur lokal auf deinem Rechner vor und wurde nicht ins Internet übertragen. Falls du dich mit PGP auskennst, kannst du dir diese all-in-one HTML-Seite herunterladen. Um zu überprüfen, ob die heruntergeladene Version authentisch ist, kannst du den SHA1-Hash dieser Seite mit dem SHA1-Hash in der signierten Versionsgeschichte am unteren Ende dieser Seite abgleichen. Wenn du diese Seite verlässt, sie neulädst bzw. den \"Neues Wallet erstellen\"-Button drückst, wird ein neues Wallet erstellt und das vorherige wird nicht mehr abrufbar sein. Du solltest deinen privaten Schlüssel geheim halten. Wer den privaten Schlüssel hat, kann damit auf alle im Wallet befindlichen Bitcoin zugreifen und sie nach Belieben ausgeben. Behandle dein gedrucktes Wallet wie echtes Geld!",
|
||||
"singletip3": "Du kannst <b>Guthaben</b> zu deinem Wallet <b>hinzufügen</b>, indem du genau wie bei anderen Überweisungen Bitcoins an die Bitcoin-Adresse deines Wallets schickst.",
|
||||
"singletip4": "<b>Überprüfe dein Guthaben,</b> indem du deine Bitcoin-Adresse auf blockchain.info bzw. blockexplorer.com eingibst.",
|
||||
"singletip5": "Du kannst deine <b>Bitcoins ausgeben</b>, indem du das gesamte mit deinem privaten Schlüssel verbundene Guthaben auf deinen Account bei blockchain.info bzw. mtgox.com überträgst. Alternativ kannst du dir ein Bitcoinprogramm herunterladen und deinen privaten Schlüssel in dieses importieren. Beachte dabei aber, dass, sobald du Bitcoins mit dem Programm sendest, dein privater Schlüssel mit den anderen privaten Schlüsseln, die vom Programm bereitgestellt werden, verbunden wird. Bei einer Überweisung wird etwas Rückgeld an eine der Bitcoin-Adressen des Programms geschickt. Deswegen musst du, um tatsächlich dein gesamtes Guthaben zu sichern, ein Backup vom gesamten Wallet des Programms, das nun auch deinen importierten privaten Schlüssel enthält, anfertigen. Satoshi rät, dass man unter keinen Umständen ein Wallet löschen sollte.",
|
||||
"singletip5": "Du kannst deine <b>Bitcoins ausgeben</b>, indem du das gesamte mit deinem privaten Schlüssel verbundene Guthaben auf deinen Account bei blockchain.info überträgst. Alternativ kannst du dir ein Bitcoinprogramm herunterladen und deinen privaten Schlüssel in dieses importieren. Beachte dabei aber, dass, sobald du Bitcoins mit dem Programm sendest, dein privater Schlüssel mit den anderen privaten Schlüsseln, die vom Programm bereitgestellt werden, verbunden wird. Bei einer Überweisung wird etwas Rückgeld an eine der Bitcoin-Adressen des Programms geschickt. Deswegen musst du, um tatsächlich dein gesamtes Guthaben zu sichern, ein Backup vom gesamten Wallet des Programms, das nun auch deinen importierten privaten Schlüssel enthält, anfertigen. Satoshi rät, dass man unter keinen Umständen ein Wallet löschen sollte.",
|
||||
"singleshare": "SHARE", //TODO: please translate
|
||||
"singlesecret": "SECRET", //TODO: please translate
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "Grafische Gestaltung ausblenden?",
|
||||
|
@ -772,7 +796,7 @@ ninja.translator = {
|
|||
"singletip2": "<b>Pro zabezpečení této peněženky</b> musíte tuto Bitcoin adresu a soukromý klíč vytisknout a nebo jinak poznamenat. Je důležité provést zálohu soukromého klíče a jeho uschování na bezpečném místě. Tato webová stránka nemá žádné informace o vašem soukromém klíči. Pokud ovládáte PGP, můžete celou tuto stránku stáhnout v jednom HTML souboru a ověřit její pravost srovnáním SHA1 hashe s podepsaným dokumentem historie verzí. Odkaz naleznete v patičce této stránky. Pokud opustíte či obnovíte tuto stránku nebo kliknete na 'Vytvořit novou adresu' dojde k vygenerování nového soukromého klíče a předtím zobrazený klíč bude ztracen. Váš soukromý klíč musíte uchovat v tajnosti. Každý kdo má tento klíč k dispozici může utratit všechny peníze v této peněžence. Pokud budete peněženku tisknout, uzavřete ji do nepropustného obalu nebo ji zalaminujte. Tím zabráníte jejímu poškození vodou. Chovejte se k této peněžence jako k normálním bankovkám.",
|
||||
"singletip3": "<b>Pro vložení</b> peněz do této peněženky stačí zaslat peníze na Bitcoin adresu.",
|
||||
"singletip4": "<b>Zkontrolovat zůstatek</b> můžete na webové stránce blockchain.info nebo blockexplorer.com po zadání Bitcoin adresy.",
|
||||
"singletip5": "<b>Utratit Bitcoiny</b> můžete pomocí blockchain.info či mtgox.com načtením celého zůstatku pomocí soukromého klíče do vašeho účtu. Utratit zůstatek můžete také pomocí jednoho z P2P Bitcoin klientů naimportováním soukromého klíče. Myslete na to, že importem klíče do klienta se stane součástí jeho peněženky. Pokud převedete někomu peníze, nespotřebovaný zůstatek se zašle na jinou Bitcoin adresu uvedenou v P2P klienta. Tuto novou adresu musíte vyzálohovat a udržovat v bezpečí. Satoshi doporučuje, že by nikdo nikdy neměl mazat peněženku.",
|
||||
"singletip5": "<b>Utratit Bitcoiny</b> můžete pomocí blockchain.info načtením celého zůstatku pomocí soukromého klíče do vašeho účtu. Utratit zůstatek můžete také pomocí jednoho z P2P Bitcoin klientů naimportováním soukromého klíče. Myslete na to, že importem klíče do klienta se stane součástí jeho peněženky. Pokud převedete někomu peníze, nespotřebovaný zůstatek se zašle na jinou Bitcoin adresu uvedenou v P2P klienta. Tuto novou adresu musíte vyzálohovat a udržovat v bezpečí. Satoshi doporučuje, že by nikdo nikdy neměl mazat peněženku.",
|
||||
"singleshare": "SDÍLEJTE",
|
||||
"singlesecret": "SOUKROMÉ",
|
||||
|
||||
|
@ -845,7 +869,7 @@ ninja.translator = {
|
|||
"detaillabelbitcoinaddresscomp": "Komprimovaná bitcoin adresa:",
|
||||
"detaillabelpublickey": "Veřejný klíč (130 znaků [0-9A-F]):",
|
||||
"detaillabelpublickeycomp": "Komprimovaný veřejný klíč (66 znaků [0-9A-F]):",
|
||||
"detaillabelprivwif": "Soukromý klíč WIF <br />51 znaků v base58, začíná '5'",
|
||||
"detaillabelprivwif": "Soukromý klíč WIF <br />51 znaků v base58, začíná",
|
||||
"detaillabelprivwifcomp": "Komprimovaný soukromý klíč WIF <br />52 znaků v base58, začíná",
|
||||
"detailcompwifprefix": "'K' nebo 'L'",
|
||||
"detaillabelprivhex": "Soukromý klíč v hexadecimálním formátů (64 znaků [0-9A-F]):",
|
||||
|
@ -857,34 +881,178 @@ ninja.translator = {
|
|||
"detaila1": "Důležitá součást vytváření Bitcoin peněženky je jistota, že náhodná čísla použitá pro její tvorbu jsou opravdu náhodná. Fyzická náhoda je lepší než počítačem generovaná pseudonáhoda. Pomocí hrací kostky je možné jednoduše získat fyzicky náhodná čísla. Pro vytvoření soukromého klíče potřebujete pouze šestihrannou kostku, kterou 99x hodíte. Každý tento hod zaznamenejte. Při zapisování převeďte čísla takto: 1=1, 2=2, 3=3, 4=4, 5=5, 6=0. Pomocí této techniky zapisujete velké, opravdu náhodné číslo, svůj soukromý klíč v B6 nebo také base 6 formátu. Těchto 99 čísel napište do pole výše a klikněte na Zobrazit detail. Poté se vám zobrazí Bitcoin adresa přidružená k tomuto soukromému klíči. Soukromý klíč byste si měli zaznamenat také ve WIF formátu, který je široce používán."
|
||||
},
|
||||
|
||||
"hu": { // 02-MAR-2014 16:57
|
||||
// javascript alerts or messages
|
||||
"testneteditionactivated": "TESTNET KIADÁS AKTIVÁLVA",
|
||||
"paperlabelbitcoinaddress": "Bitcoin cím:",
|
||||
"paperlabelprivatekey": "Privát kulcs (WIF, tárca import formátumban):",
|
||||
"paperlabelencryptedkey": "Titkosított privát kulcs (Jelszó szükséges)",
|
||||
"bulkgeneratingaddresses": "Cím generálás... ",
|
||||
"brainalertpassphrasetooshort": "A megadott jelmondat túl rövid.\n\n",
|
||||
"brainalertpassphrasewarning": "Figyelem: Fontos, hogy erős jelmondatot válasszon, mert különben a jelmondatot nyers erővel feltörhetik és a bitcoinjait ellophatják.",
|
||||
"brainalertpassphrasedoesnotmatch": "A jelmondat és az ellenőrző jelmondat nem azonos.",
|
||||
"detailalertnotvalidprivatekey": "A beadott szöveg nem érvénytelen Privát Kulcs",
|
||||
"detailconfirmsha256": "Az ön által beadott szöveg érvénytelen Privát Kulcs!\n\nSzeretné a beadott szöveget jelmondatként kezelni, és annak SHA256 zanzájából egy Privát Kulcsot előállítani?\n\nFigyelem: Fontos, hogy erős jelmondatot válasszon, mert különben a jelmondatot nyers erővel feltörhetik és a bitcoinjait ellophatják.",
|
||||
"bip38alertincorrectpassphrase": "Érvénytelen jelmondat a titkosított privát kulcshoz.",
|
||||
"bip38alertpassphraserequired": "A BIP38 kulcshoz jelmondat szükséges",
|
||||
"vanityinvalidinputcouldnotcombinekeys": "Érvénytelen bemenet. A kulcsok nem tartoznak össsze.",
|
||||
"vanityalertinvalidinputpublickeysmatch": "Érvénytelen bemenet. A két megadott nyilvános kulcs azonos. Két különböző kulcs bevitelére van szükség.",
|
||||
"vanityalertinvalidinputcannotmultiple": "Érvénytelen bemenet. Két nyilvános kulcs összeszorzása nem lehetséges. Válassza az 'Összeadás'-t, ha két nyilvános kulcsból szeretne egy bitcoin címet kapni.",
|
||||
"vanityprivatekeyonlyavailable": "Csak két privát kulcs kombinálásakor lehetséges",
|
||||
"vanityalertinvalidinputprivatekeysmatch": "Érvénytelen bemenet. A két megadott privát kulcs azonos. Két különböző kulcs bevitelére van szükség.",
|
||||
|
||||
// header and menu html
|
||||
"tagline": "Nyílt forráskódú, kliens oldali JavaScript, Bitcoin pénztárca előállítására",
|
||||
"generatelabelbitcoinaddress": "A bitcoin cím előállítása...",
|
||||
"generatelabelmovemouse": "MOZGASSA az egeret, ha fokozni szeretné a véletlenszerűséget...",
|
||||
"generatelabelkeypress": "VAGY gépeljen be néhány véletlenszerű karaktert ebbe a szövegdobozba",
|
||||
"singlewallet": "Egyszerű pénztárca",
|
||||
"paperwallet": "Papír pénztárca",
|
||||
"bulkwallet": "Tömeges pénztárca",
|
||||
"brainwallet": "Fejben tartott pénztárca",
|
||||
"vanitywallet": "Kérkedő pénztárca",
|
||||
"splitwallet": "Részekre bontott ~",
|
||||
"detailwallet": "A pénztárca részletei",
|
||||
|
||||
// footer html
|
||||
"footerlabeldonations": "Adományok:",
|
||||
"footerlabeltranslatedby": "Fordította: 1GEBor11XtqDoamipB8nAV7o4fNW5JcrUD",
|
||||
"footerlabelpgp": "PGP",
|
||||
"footerlabelversion": "Változatok története",
|
||||
"footerlabelgithub": "GitHub kódtár",
|
||||
"footerlabelcopyright1": "Copyright bitaddress.org.",
|
||||
"footerlabelcopyright2": "Az egyes JavaScript kódok szerzőinek jogai a forráskódon belül találhatók meg.",
|
||||
"footerlabelnowarranty": "Garancia nincs.",
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Új cím előállítása",
|
||||
"singleprint": "Nyomtatás",
|
||||
"singlelabelbitcoinaddress": "Bitcoin cím:",
|
||||
"singlelabelprivatekey": "Privát kulcs (WIF, tárca import formátumban):",
|
||||
"singletip1": "<b>Egy bitcoin pénztárca</b> nem más, mint egy bitcoin címből és a hozzá tartozó privát kulcsból álló számpár. Egy ilyen pénztárcát állítottunk elő és jelenítettünk meg fent az Ön számára a Web böngészőben.",
|
||||
"singletip2": "<b>A pénztárca biztonságos megőrzése</b> érdekében nyomtassa ki vagy más módon rögzítse a bitcoin címet és privát kulcsot. Fontos, hogy a privát kulcsból készítsen másolatot, és tárolja biztonságos helyen. Ez a webhely nem tud az ön privát kulcsairól. Ha ismeri a PGP-t, akkor egyben letöltheti az egész web lapot, és ellenőrizheti, hogy a webhely szerzője álatal írt valódi változatot töltötte-e le. Ehhez össze kell hasonlítania a HTML-ből képzett SHA1 zanzát a webhely láblécében hivatkozott, aláírt verzió történetben lévő SHA1 zanzával. Ha elhagyja/megfrissíti a webhelyet vagy megnyomja az 'Új cím előállítása' gombot, akkor egy új privát kulcs áll elő, és az előzőleg megjelenített privát kulcs elvész. A bitcoin címhez tartozó privát kulcsot titokban kell tartani. Bárki, aki megszerzi ezt a kulcsot, el tudja költeni az ehhez a címhez tartozó összes bitcoint. Ha kinyomtatja a pénztárcát, akkor tárolja egy villámzáras vízhatlan nylon-zacskóban. A papír pénztárcát tekintse úgy, mintha pénz lenne.",
|
||||
"singletip3": "<b>Pénzt úgy tehet</b> a pénztárcájába, hogy másokkal bitcoinokat küldet erre a Bitcoin címre.",
|
||||
"singletip4": "<b>A pénztárca egyenlegét</b> úgy kérdezheti le, hogy elmegy a blockchain.info vagy a blockexplorer.com weblapokra, és ott beadja ezt a Bitcoin címet.",
|
||||
"singletip5": "<b>Ha el akarja költeni a bitcoinjait,</b> akkor menjen a blockchain.info weblapra, és a privát kulcson lévő teljes egyenleget töltse át (sweep) a weblapon lévő számlájára. A pénzt úgy is elköltheti, hogy letölti valamelyik népszerű p2p bitcoin klienst, és beimportálja a privát kulcsot a p2p kliens pénztárcájába. Ne feledje, hogy miután beimportálta a kulcsot a p2p bitcoin kliensbe, a kulcsot a p2p kliens a pénztárcában lévő többi kulccsal együtt tárolja. Pénz küldésekor a visszajáró pénzt a p2p kliens pénztárcájában lévő másik bitcoin címre fogják küldeni. Ekkor biztonsági másolatot kell készítenie a p2p kliens pénztárcáról, és a másolatot biztos helyen kell őriznie, mivel a maradék bitcoinjait a pénztárca kulcsai tárolják. Satoshi tanácsa, hogy pénztárcát soha ne töröljünk.",
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "A grafika elrejtése?",
|
||||
"paperlabeladdressesperpage": "Címek száma egy oldalon:",
|
||||
"paperlabeladdressestogenerate": "Előállítandó címek száma:",
|
||||
"papergenerate": "Előállítás",
|
||||
"paperprint": "Nyomtatás",
|
||||
"paperlabelBIPpassphrase": "Jelmondat:",
|
||||
"paperlabelencrypt": "BIP38 titkosítás?",
|
||||
|
||||
// bulk wallet html
|
||||
"bulklabelstartindex": "Kezdő index:",
|
||||
"bulklabelrowstogenerate": "Az előállítandó sorok száma:",
|
||||
"bulklabelcompressed": "Tömörített címek használata?",
|
||||
"bulkgenerate": "Előállítás",
|
||||
"bulkprint": "Nyomtatás",
|
||||
"bulklabelcsv": "Vesszővel elválasztott értékek (CSV):",
|
||||
"bulklabelformat": "Index, Cím, Privát cím (WIF)",
|
||||
"bulklabelq1": "Miért jó a Tömeges pénztárca használata, ha Ön bitcoint szeretne elfogadni a web-en?",
|
||||
"bulka1": "Ha Ön bitcoint szeretne elfogadni a web-en, akkor a szokásos megoldás az, hogy installálja a hivatalos bitcoin kliens démont (\"bitcoind\"). Sok web szolgáltató nem támogatja a bitcoin démon installálását. Ráadásul, ha a bitcoin démont a web szerveren futtatja, akkor a privát kulcsai is a web szerveren lesznek tárolva, és a web szerver meghekkelésekor ellophatják őket. A Tömeges pénztárca használatakor csak a bitcoin címeket kell feltölteni a web szerverre, a privát kulcsokat nem. Így nem kell aggódnia, hogy ellopják a bitcoin pénztárcáját, ha betörnek a web szerverre.",
|
||||
"bulklabelq2": "Hogyan használható a Tömeges pénztárca az Ön web helyén bitcoin elfogadásra?",
|
||||
"bulklabela2li1": "A Tömeges pénztárcával állítson elő nagy mennyiségű (10,000+) bitcoin címet. Másolja át a vesszővel elválasztott adatokat (CSV) egy biztonságos szöveges állományba a számítógépére. A szöveges állományról készítsen mentést, és azt őrizze biztonságos környezetben.",
|
||||
"bulklabela2li2": "Importálja be a Bitcoin címeket a web szerverén futó adatbázisba. (A pénztárca privát kulcsait ne importája be, mert ezzel azt kockáztatja, hogy a hackerek ellopják a pénzét. Csak a bitcoin címeket importálja be, úgy, ahogy azt a ügyfelei látják majd.)",
|
||||
"bulklabela2li3": "Web helyének vásárlókosarába vegye fel a bitcoinnal történő fizetés lehetőségét. Ha egy ügyfél bitcoinnal kíván fizetni, akkor \"fizetési címként\" az adatbázis egyik címét jelenítse meg, és a megrendelés mellett ezt a címet tárolja.",
|
||||
"bulklabela2li4": "Most szüksége van arra, hogy értesítést kapjon, ha megérkezett a pénz. A Google-on keressen rá a \"bitcoin payment notification\" kifejezésre, és iratkozzon föl valamelyik szolgáltatóhoz, amely értesítést küld, ha bizonyos címekre Bitcoint küldtek. Számos ilyen szolgáltató van, amelyik Web szervíz, API, SMS, Email, stb. segítségével értesítést küld. Amint megérkezik az értesítés, amelynek automatikus figyelése beprogramozható, máris megkezdheti az ügyfél megrendelésének feldolgozását. Ha manuálisan szeretné ellenőrizni, hogy érkezett-e valamelyik címre pénz, akkor a Block Explorer-t használhatja. A CÍM helyébe írja azt a Bitcoin címet, amelyet ellenőrizni szeretne. A tranzakció megerősítéséhez 10 és 60 perc közötti időre van szükség.<br />http://www.blockexplorer.com/address/CÍM<br /><br />A megerősítetlen tranzakciókat itt lehet megnézni: http://blockchain.info/ <br />A tranzakció 30 másodpercen belül megjelenik.",
|
||||
"bulklabela2li5": "Az Ön bitcoinjai biztonságos módon gyűlnek a blokkláncon. Használja az 1. lépés során előállított eredeti pénztárcát, ha szeretné őket elkölteni.",
|
||||
|
||||
// brain wallet html
|
||||
"brainlabelenterpassphrase": "Adja be a jelmondatot: ",
|
||||
"brainlabelshow": "Jelmondat megjelenítése?",
|
||||
"brainprint": "Nyomtatás",
|
||||
"brainlabelconfirm": "Erősítse meg a jelmondatot: ",
|
||||
"brainview": "Megjelenítés",
|
||||
"brainalgorithm": "Algoritmus: SHA256(jelmondat)",
|
||||
"brainlabelbitcoinaddress": "Bitcoin cím:",
|
||||
"brainlabelprivatekey": "Privát kulcs (WIF, tárca import formátumban):",
|
||||
|
||||
// vanity wallet html
|
||||
"vanitylabelstep1": "1. lépés - az \"1. lépéshez tartozó Kulcspár\" előállítása",
|
||||
"vanitynewkeypair": "Előállítás",
|
||||
"vanitylabelstep1publickey": "1. lépés, Publikus Kulcs:",
|
||||
"vanitylabelstep1pubnotes": "Másolja a fentiekeket a Vanity Pool webhely Your-Part-Public-Key ('az ön publikus kulcsa') mezőjébe.",
|
||||
"vanitylabelstep1privatekey": "1. lépés, Privát Kulcs:",
|
||||
"vanitylabelstep1privnotes": "Másolás és beillesztés segítségével másolja a fenti Privát Kulcsot egy szöveges állományba. Ideális esetben a szöveges állomány egy titkosított meghajtón van. Ha a Vanity Pool megtalálta az Ön által megadott előtaghoz tartozó Privát Kulcsot, akkor lesz szüksége erre az állományra, hogy elő tudja állítani a Privát Kulcsot.",
|
||||
"vanitylabelstep2calculateyourvanitywallet": "2. lépés - A Kérkedő Pénztárca Privát Kulcsának kiszámítása",
|
||||
"vanitylabelenteryourpart": "Adja meg az Önhöz tartozó Privát Kulcsot (amelyet az 1. lépésben állított elő és mentett el):",
|
||||
"vanitylabelenteryourpoolpart": "Adja meg a Pool-hoz tartozó Privát Kulcsot (amely a Vanity Pool-ból származik):",
|
||||
"vanitylabelnote1": "[MEGJEGYZÉS: ebbe a szövegmezőbe publikus kulcs vagy privát kulcs egyaránt írható]",
|
||||
"vanitylabelnote2": "[MEGJEGYZÉS: ebbe a szövegmezőbe publikus kulcs vagy privát kulcs egyaránt írható]",
|
||||
"vanitylabelradioadd": "Összeadás",
|
||||
"vanitylabelradiomultiply": "Szorzás",
|
||||
"vanitycalc": "A Kérkedő pénztárca kiszámítása",
|
||||
"vanitylabelbitcoinaddress": "Kérkedő Bitcoin cím:",
|
||||
"vanitylabelnotesbitcoinaddress": "Fönt látható az ön új címe, mely magában foglalja a kívánt előtagot.",
|
||||
"vanitylabelpublickeyhex": "Kérkedő Publikus Kulcs (HEX):",
|
||||
"vanitylabelnotespublickeyhex": "A Publikus Kulcs hexadecimális alakban. ",
|
||||
"vanitylabelprivatekey": "Kérkedő Privát Kulcs (WIF):",
|
||||
"vanitylabelnotesprivatekey": "Ez az Ön Privát Kulcsa, mellyel elérheti a pénzét. ",
|
||||
|
||||
// split wallet html
|
||||
"splitlabelthreshold": "A visszaállításhoz szükséges részek minimális száma",
|
||||
"splitlabelshares": "Részek száma",
|
||||
"splitview": "Előállítás",
|
||||
"combinelabelentershares": "Adja be a meglévő részeket (Enter-rel, szóközzel vagy más whitespace karakterrel elválasztva)",
|
||||
"combineview": "A részek összekombinálása",
|
||||
"combinelabelprivatekey": "Visszaállított Privát Kulcs",
|
||||
|
||||
// detail wallet html
|
||||
"detaillabelenterprivatekey": "Adja meg a Privát Kulcsot",
|
||||
"detailkeyformats": "Kulcs formátumok: WIF, WIFC, HEX, B64, B6, MINI, BIP38",
|
||||
"detailview": "Részletek megjelenítése",
|
||||
"detailprint": "Nyomtatás",
|
||||
"detaillabelnote1": "A Bitcoin Privát Kulcs egy titkos szám, melyet csak Ön ismer. Számos különböző formátumban kódolható. Az alábbiakban megjelenítettük a a Privát Kulcshoz tartozó Bitcoin Címet és Publikus kulcsot, valamint a Privát Kulcsot a legnépszerűbb kódolási formátumokban (WIF, WIFC, HEX, B64, MINI).",
|
||||
"detaillabelnote2": "A Bitcoin v0.6+ a publikus kulcsokat tömörített formátumban tárolja. A kliens az importprivkey/dumpprivkey parancsokkal a privát kulcsok importálását és exportálását is támogatja. Az exportált privát kulcsok formátumát csupán a Bitcoin pénztárca verziószáma határozza meg.",
|
||||
"detaillabelbitcoinaddress": "Bitcoin cím:",
|
||||
"detaillabelbitcoinaddresscomp": "Tömörített Bitcoin cím:",
|
||||
"detaillabelpublickey": "Publikus Kulcs (130 karakter [0-9A-F]):",
|
||||
"detaillabelpublickeycomp": "Tömörített Publikus Kulcs (66 karakter [0-9A-F]):",
|
||||
"detaillabelprivwif": "WIF Privát Kulcs <br />51 db base58 karakter, melynek kezdete",
|
||||
"detaillabelprivwifcomp": "Tömörített WIF Privát Kulcs <br />52 db base58 karakter, melynek kezdete",
|
||||
"detailcompwifprefix": "'K' vagy 'L'",
|
||||
"detaillabelprivhex": "Hexadecimális formátumú Privát Kulcs (64 karakter [0-9A-F]):",
|
||||
"detaillabelprivb64": "Base64 formátumú Privát Kulcs (44 karakter):",
|
||||
"detaillabelprivmini": "Mini formátumú Privát Kulcs (22, 26 vagy 30 karakter, amely egy 'S'-sel kezdődik):",
|
||||
"detaillabelpassphrase": "BIP38 jelmondat",
|
||||
"detaildecrypt": "BIP38 dekódolás",
|
||||
"detaillabelq1": "Hogyan lehet dobókockával pénztárcát készíteni? Mit jelent a B6 formátum?",
|
||||
"detaila1": "Egy Bitcoin pénztárca előállításakor nagyon fontos, hogy a felhasznált véletlen számok valóban véletlenek legyenek. A fizikai véletlen jobb, mint a számítógéppel előállított pszeudo-véletlen. Fizikai véletlen a legegyszerűbben egy dobókockával állítható elő. Ha szeretne egy Bitcoin privát címet előállítani, akkor csupán egy dobókockára van szüksége, mellyel 99-szer kell dobni. Jegyezze fel minden egyes dobása eredményét. Az eredmények feljegyzésekor a következő szabályokat kövesse: 1->1, 2->2, 3->3, 4->4, 5->5, 6->0. Ha így tesz, akkor a privát kulcshoz tartozó véletlen számot B6 formátumban, vagyis 6-os számrendszerben rögzíti. Írja be ezt a 99 karakterből álló 6-os számrendszerbeli privát kulcsot a fenti szövegmezőbe, majd nyomja meg a 'Részletek megjelenítése' gombot. Ekkor megjelenik az a Bitcoin cím, amely ehhez a privát kulcshoz tartozik. Érdemes felírni a WIF formátumú privát kulcsot is, mivel ezt szélesebb körben használják."
|
||||
},
|
||||
>>>>>>> 6528084a65e4ddcc94fca96d012bbd15537b3f01
|
||||
|
||||
"jp": {
|
||||
// javascript alerts or messages
|
||||
"testneteditionactivated": "テストネット版が有効になりました。",
|
||||
"paperlabelbitcoinaddress": "ビットコインアドレス",
|
||||
"paperlabelprivatekey": "プライベートキー(WIF形式)",
|
||||
"paperlabelencryptedkey": "暗号化されたプライベートキー(パスワード必須)",
|
||||
"bulkgeneratingaddresses": "アドレス生成...",
|
||||
"bulkgeneratingaddresses": "アドレス生成中...",
|
||||
"brainalertpassphrasetooshort": "パスワードが短すぎます \n\n",
|
||||
"brainalertpassphrasewarning": "注意:強いパスワードを選ばないとプライベートキーを安易に当てられてしまいます。<br>なお、<b>UTF-8の文字も使えるため、キーボードが半角か全角か今一度ご確認下さい。</b>",
|
||||
"brainalertpassphrasedoesnotmatch": "パスワードの不一致",
|
||||
"brainalertpassphrasewarning": "注意:強いパスワードを選ばないとプライベートキーを安易に当てられてビットコインを盗まれてしまいます。<br>なお、<b>UTF-8の文字も使えるため、キーボードが半角か全角か今一度ご確認下さい。</b>",
|
||||
"brainalertpassphrasedoesnotmatch": "パスワードが一致しません",
|
||||
"detailalertnotvalidprivatekey": "入力された文字列は有効なプライベートキーではありません。",
|
||||
"detailconfirmsha256": "入力された文字列は有効なプライベートキーではありません。\n\nこの文字列をパスワード代わりにして、それをSHA256ハッシュ取ってプライベートキーを生成しますか?\n\n注意強いパスワードを選ばないとプライベートキーを安易に当てられてしまいます。",
|
||||
"bip38alertincorrectpassphrase": "この暗号化されたプライベートキーに一致しないパスワードです。",
|
||||
"bip38alertpassphraserequired": "BIP38キー生成するにはパスワードをかける必要があります。",
|
||||
"vanityinvalidinputcouldnotcombinekeys": "不正入力キーを結合できませんでした。",
|
||||
"vanityalertinvalidinputpublickeysmatch": "不正入力両方のパブリックキーがチケットに一致します。2つの異なるキーをお使い下さい。",
|
||||
"vanityalertinvalidinputcannotmultiple": "不正入力2つのパブリックキーを掛け合わせることはできません。「Add」を選択し、2つのパブリックキーを足し合わせてアドレスを生成して下さい。",
|
||||
"vanityprivatekeyonlyavailable": "2つのプライベートキーを合わせた時だけ有効です。",
|
||||
"detailconfirmsha256": "入力された文字列は有効なプライベートキーではありません。\n\n代わりにこの文字列をパスワードとして、SHA256ハッシュを用いプライベートキーを生成しますか?\n\n注意: 強いパスワードを選ばないとプライベートキーを安易に当てられてビットコインを盗まれてしまいます。",
|
||||
"bip38alertincorrectpassphrase": "暗号化されたプライベートキーに一致しないパスワードです。",
|
||||
"bip38alertpassphraserequired": "BIP38キーを生成するにはパスワードをかける必要があります。",
|
||||
"vanityinvalidinputcouldnotcombinekeys": "不正入力です。キーを結合できませんでした。",
|
||||
"vanityalertinvalidinputpublickeysmatch": "不正入力です。両方のパブリックキーが同じです。2つの異なるキーをお使い下さい。",
|
||||
"vanityalertinvalidinputcannotmultiple": "不正入力です。2つのパブリックキーを掛け合わせることはできません。「足し算」を選択し、2つのパブリックキーを足し合わせてアドレスを生成して下さい。",
|
||||
"vanityprivatekeyonlyavailable": "2つのプライベートキーを掛け合わせた時だけ有効です。",
|
||||
"vanityalertinvalidinputprivatekeysmatch": "不正入力両方のプライベートキーがチケットに一致します。2つの異なるキーをお使い下さい。",
|
||||
|
||||
// header and menu html
|
||||
"tagline": "クライエント側ビットコインアドレス生成(javascript使用)",
|
||||
"generatelabelbitcoinaddress": "ビットコインアドレスを生成...",
|
||||
"generatelabelmovemouse": "マウスを素早く動かしてエントロピーを作って下さい。",
|
||||
"generatelabelkeypress": "若しくはこちらの入力欄にランダムなキーを打ってご入力下さい。",
|
||||
"tagline": "クライエント側ビットコインアドレス生成(JavaScript使用)",
|
||||
"generatelabelbitcoinaddress": "ビットコインアドレスを生成中...",
|
||||
"generatelabelmovemouse": "マウスを動かして、ランダム要素を追加してください。",
|
||||
"generatelabelkeypress": "もしくはこちらの入力欄にランダムな文字を打って下さい。",
|
||||
"singlewallet": "シングルウォレット",
|
||||
"paperwallet": "ペーパーウォレット",
|
||||
"bulkwallet": "大量ウォレット生成",
|
||||
"bulkwallet": "大量ウォレット",
|
||||
"brainwallet": "暗記ウォレット",
|
||||
"vanitywallet": "カスタムウォレット",
|
||||
"detailwallet": "ウォレットの詳細",
|
||||
|
@ -894,41 +1062,41 @@ ninja.translator = {
|
|||
"footerlabeltranslatedby": "日本語訳寄付先 1o3EBhxPhGn8cGCL6Wzi5F5kTPuBofdMf",
|
||||
"footerlabelpgp": "PGP",
|
||||
"footerlabelversion": "バージョン履歴",
|
||||
"footerlabelgithub": "GitHubレポジトリー",
|
||||
"footerlabelcopyright1": "Copyright bitaddress.org .",
|
||||
"footerlabelcopyright2": "JavaScriptのコピーライト情報はソースに含まれている。",
|
||||
"footerlabelgithub": "GitHubリポジトリ",
|
||||
"footerlabelcopyright1": "Copyright bitaddress.org.",
|
||||
"footerlabelcopyright2": "JavaScriptのコピーライト情報はソースに含まれています。",
|
||||
"footerlabelnowarranty": "保障はありません。",
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "アドレス生成",
|
||||
"newaddress": "新アドレス生成",
|
||||
"singleprint": "印刷",
|
||||
"singlelabelbitcoinaddress": "ビットコインアドレス",
|
||||
"singlelabelprivatekey": "プライベートキー (WIF形式)",
|
||||
"singletip1": "<b>ビットコインウォレットとは</b>一番シンプルな要素としてビットコインアドレスとビットコインプライベートキーのペアがあれば、ビットコインウォレットと言える。ブラウザーの処理の中で新しいアドレスを生成し、上記にて表示します。",
|
||||
"singletip2": "このウォレットを守るためには、ビットコインアドレスとビットコインプライベートキーを何らかの手段で記録しなければいけません。プライベートキーが無いとペアになっているアドレスに送られたビットコインが使えないので、人に晒されないような方法でプライベートキーのコピーや複写を取り、大事に保管して下さい。このサイトはこのプライベートキーを記録しません。PGPをご存知の方は、このサイトを1つのhtmlファイルで落とすことができるので、このサイトのhtmlファイルのSHA1ハッシュとサイトのフッターにデジタル署名されたメッセージに入ったハッシュを比べて不正にいじられていないかをお確かめいただけます。このページを閉じたり、離れたりすると現在表示されているビットコインが消えてなくなりますので、ご使用の場合は必ず何らかの手段で記録しておいて下さい。",
|
||||
"singletip3": "<b>残高を増やそう。</b>ビットコインアドレスを友達にあげて、ビットコインを送ってもらってみて下さい。このビットコインアドレス宛に送られたビットコインの送金権はあなたのプライベートキーにあります。",
|
||||
"singletip4": "<b>残高照会</b>はblockchain.infoやblockexplorer.comに行き、ビットコインアドレスを入力してお調べ下さい。",
|
||||
"singletip5": "<b>ビットコインを使おう。</b>送金するには、このページで生成したプライベートキーをblockchain.infoのウォレットや各種パソコン・スマホ端末にあるウォレットアプリなどに取り込んで使えます。しかし、その時点でそのアドレスが取り込んだウォレットの他のアドレスと融合してしまい、この一つのアドレスのバックアップだけじゃビットコインを保管することはできなくなります。取り込み先のウォレットを強いパスワードで暗号化し、バックアップして、安全に扱って下さい。ビットコインの考案者「サトシさん」曰く、「一度作ったウォレットを、空にしたとしても、削除しない方が良い。」(メールアドレスと同じく、いつ昔の友達や親戚から古いアドレス宛にビットコインを送ってくるかわかりませんから。)",
|
||||
"singletip1": "<b>ビットコインウォレットとは</b> ビットコインのアドレスと対応するプライベートキーを組み合わせたものです。新しいアドレスがブラウザー上で生成され、上記に表示されています。",
|
||||
"singletip2": "<b>このウォレットを守るためには</b> ビットコインアドレスとビットコインプライベートキーを印刷するなどの手段で記録しなければいけません。プライベートキーが無いとペアになっているアドレスに送られたビットコインが使えないので、人に晒されないような方法でプライベートキーのコピーを取り、大事に保管して下さい。このサイトはこのプライベートキーの保存はしません。PGPをご存知の方は、このサイトを1つのhtmlファイルで落とすことができるので、このサイトのhtmlファイルのSHA1ハッシュとサイトのフッターにデジタル署名されたメッセージに入ったハッシュを比べて不正にいじられていないかをお確かめいただけます。このページを閉じたり、離れたり、”新アドレス生成”を押すと現在表示されているプライベートキーは消え、新規アドレスが生成されるので、ご使用の場合は必ず何らかの手段で記録しておいて下さい。プライベートキーは秘密にしてください。共有されますと、対応するビットコインアドレスに存在するコインが全て共有者間で利用可能となります。ウォレット情報を印刷したら、濡れないようにジップロックに入れましょう。紙幣と同様に扱うよう心がけてください。",
|
||||
"singletip3": "<b>このウォレットにコインを追加 : </b> 他の人から自分のビットコインアドレスに送ってもらう。",
|
||||
"singletip4": "<b>残高照会は</b> blockchain.infoやblockexplorer.comに行き、ビットコインアドレスを入力してお調べ下さい。",
|
||||
"singletip5": "<b>ビットコインを使おう。</b> 送金するには、このページで生成したプライベートキーをblockchain.infoのウォレットや各種パソコン・スマホ端末にあるウォレットアプリなどに取り込んで使えます。しかし、その時点でそのアドレスが取り込んだウォレットの他のアドレスと融合してしまい、この一つのアドレスのバックアップだけじゃビットコインを保管することはできなくなります。取り込み先のウォレットを強いパスワードで暗号化し、バックアップして、安全に扱って下さい。ビットコインの考案者「サトシさん」曰く、「一度作ったウォレットを、空にしたとしても、削除しない方が良い。」(メールアドレスと同じく、いつ昔の友達や親戚から古いアドレス宛にビットコインを送ってくるかわかりませんから。)",
|
||||
|
||||
// paper wallet html
|
||||
"paperlabelhideart": "デザイン非表示",
|
||||
"paperlabeladdressesperpage": "1ページごとアドレス数",
|
||||
"paperlabeladdressestogenerate": "合計アドレス数",
|
||||
"paperlabeladdressesperpage": "1ページごとのアドレス数",
|
||||
"paperlabeladdressestogenerate": "生成するアドレス数",
|
||||
"papergenerate": "生成",
|
||||
"paperprint": "印刷",
|
||||
"paperlabelBIPpassphrase": "パスワード",
|
||||
"paperlabelencrypt": "BIP38で暗号化?",
|
||||
|
||||
// bulk wallet html
|
||||
"bulklabelstartindex": "数字の開始点",
|
||||
"bulklabelstartindex": "開始番号",
|
||||
"bulklabelrowstogenerate": "生成する行数",
|
||||
"bulklabelcompressed": "アドレスを圧縮?",
|
||||
"bulklabelcompressed": "アドレスを短縮?",
|
||||
"bulkgenerate": "生成",
|
||||
"bulkprint": "印刷",
|
||||
"bulklabelcsv": "カンマ区切り値",
|
||||
"bulklabelformat": "番号、アドレス、プライベートキー(WIF形式)",
|
||||
"bulklabelq1": "ウェブサイトでビットコインを受け付ける時、何故大量に生成しておいた方がいいのか?",
|
||||
"bulka1": "昔はビットコインをサイトで受け付けたかったら、「bitcoind」というビットコインのdaemonをサーバーにアップロードし、サーバー上で実行しなければいけませんでした。しかし、このやり方だとサーバーがハッキングされてしまった場合、プライベートキーも全て持って行かれてしまいます。大量に生成しておいて、ビットコインアドレスだけをサーバーにアップしておけば、プライベートキーを安全な場所に保管できます。",
|
||||
"bulklabelq1": "ウェブサイトでビットコインを受け付ける時、何故大量のアドレスを生成しておいた方がいいのか?",
|
||||
"bulka1": "以前はビットコインをサイトで受け付けたかったら、「bitcoind」というビットコインのシステムサービスをサーバーにアップロードし、サーバー上で実行しなければいけませんでした。しかし、このやり方だとサーバーがハッキングされてしまった場合、プライベートキーも全て持って行かれてしまいます。大量に生成しておいて、ビットコインアドレスだけをサーバーにアップしておけば、プライベートキーを安全な場所に保管できます。",
|
||||
"bulklabelq2": "どうやって大量生成を使ってサイトでビットコインを受け付けられるようにできるのか?",
|
||||
"bulklabela2li1": "大量生成タブで大量のビットコインを生成(10,000+でも可)。出てくるCSVテキストをコピーして、安全なテキストエディターで貼り付けて、安全な場所に保存しておいて下さい。一つバックアップを取り、別の場所で保管しておく(強いパスワードのかかったzipなどで)",
|
||||
"bulklabela2li2": "ビットコインアドレスをウェブサーバーにアップロード。プライベートキーはアップロードしないで下さい。ユーザーに見せたい宛先用のアドレスのみをアップロードして下さい。",
|
||||
|
|
|
@ -458,6 +458,113 @@
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// test split wallet
|
||||
testSplitAndCombinePrivateKey2of2: function () {
|
||||
// lowercase hex key
|
||||
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da"; //5HpJ4bpHFEMWYwCidjtZHwM2rsMh4PRfmZKV8Y21i7msiUkQKUW
|
||||
var numshares = 2;
|
||||
var threshold = 2;
|
||||
secrets.setRNG();
|
||||
secrets.init(7);
|
||||
|
||||
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
|
||||
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var btcKey = new Bitcoin.ECKey(combined);
|
||||
|
||||
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// Example use case #1:
|
||||
// Division of 3 shares:
|
||||
// 1 share in a safety deposit box ("Box")
|
||||
// 1 share at Home
|
||||
// 1 share at Work
|
||||
// Threshold of 2 can be redeemed in these permutations
|
||||
// Home + Box
|
||||
// Work + Box
|
||||
// Home + Work
|
||||
testSplitAndCombinePrivateKey2of3: function () {
|
||||
// lowercase hex key
|
||||
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da"; //5HpJ4bpHFEMWYwCidjtZHwM2rsMh4PRfmZKV8Y21i7msiUkQKUW
|
||||
var numshares = 3;
|
||||
var threshold = 2;
|
||||
secrets.setRNG();
|
||||
secrets.init(7);
|
||||
|
||||
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
|
||||
shares.shift();
|
||||
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var btcKey = new Bitcoin.ECKey(combined);
|
||||
|
||||
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
testSplitAndCombinePrivateKey2of4: function () {
|
||||
// uppercase hex key
|
||||
var key = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B"; //5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb
|
||||
var numshares = 4;
|
||||
var threshold = 2;
|
||||
secrets.setRNG();
|
||||
secrets.init(7);
|
||||
|
||||
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
|
||||
shares.shift();
|
||||
shares.shift();
|
||||
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var btcKey = new Bitcoin.ECKey(combined);
|
||||
|
||||
if (btcKey.getBitcoinHexFormat() != key) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// Example use case #2:
|
||||
// Division of 13 shares:
|
||||
// 4 shares in a safety deposit box ("Box")
|
||||
// 3 shares with good friend Angie
|
||||
// 3 shares with good friend Fred
|
||||
// 3 shares with Self at home or office
|
||||
// Threshold of 7 can be redeemed in these permutations
|
||||
// Self + Box (no trust to spend your coins but your friends are backing up your shares)
|
||||
// Angie + Box (Angie will send btc to executor of your will)
|
||||
// Fred + Box (if Angie hasn't already then Fred will send btc to executor of your will)
|
||||
// Angie + Fred + Self (bank fire/theft then you with both your friends can spend the coins)
|
||||
testSplitAndCombinePrivateKey7of13: function () {
|
||||
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da";
|
||||
var numshares = 12;
|
||||
var threshold = 7;
|
||||
secrets.setRNG();
|
||||
secrets.init(7);
|
||||
|
||||
var shares = ninja.wallets.splitwallet.getFormattedShares(key, numshares, threshold);
|
||||
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var btcKey = new Bitcoin.ECKey(combined);
|
||||
|
||||
if (btcKey.getBitcoinHexFormat() != key.toUpperCase()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
testCombinePrivateKeyFromXofYShares: function () {
|
||||
var key = "5K9nHKqbwc1xXpa6wV5p3AaCnubvxQDBukKaFkq7ThAkxgMTMEh";
|
||||
// these are 4 of 6 shares
|
||||
var shares = ["3XxjMASmrkk6eXMM9kAJA7qiqViNVBfiwA1GQDLvg4PVScL", "3Y2DkcPuNX8VKZwpnDdxw55wJtcnCvv2nALqe8nBLViHvck",
|
||||
"3Y6qv7kyGwgRBKVHVbUNtzmLYAZWQtTPztPwR8wc7uf4MXR", "3YD4TowZn6jw5ss8U89vrcPHonFW4vSs9VKq8MupV5kevG4"]
|
||||
secrets.setRNG();
|
||||
secrets.init(7);
|
||||
|
||||
var combined = ninja.wallets.splitwallet.combineFormattedShares(shares);
|
||||
var btcKey = new Bitcoin.ECKey(combined);
|
||||
if (btcKey.getBitcoinWalletImportFormat() != key) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
532
src/secrets.js
Normal file
532
src/secrets.js
Normal file
|
@ -0,0 +1,532 @@
|
|||
// secrets.js - by Alexander Stetsyuk - released under MIT License
|
||||
(function(exports, global){
|
||||
var defaults = {
|
||||
bits: 8, // default number of bits
|
||||
radix: 16, // work with HEX by default
|
||||
minBits: 3,
|
||||
maxBits: 20, // this permits 1,048,575 shares, though going this high is NOT recommended in JS!
|
||||
|
||||
bytesPerChar: 2,
|
||||
maxBytesPerChar: 6, // Math.pow(256,7) > Math.pow(2,53)
|
||||
|
||||
// Primitive polynomials (in decimal form) for Galois Fields GF(2^n), for 2 <= n <= 30
|
||||
// The index of each term in the array corresponds to the n for that polynomial
|
||||
// i.e. to get the polynomial for n=16, use primitivePolynomials[16]
|
||||
primitivePolynomials: [null,null,1,3,3,5,3,3,29,17,9,5,83,27,43,3,45,9,39,39,9,5,3,33,27,9,71,39,9,5,83],
|
||||
|
||||
// warning for insecure PRNG
|
||||
warning: 'WARNING:\nA secure random number generator was not found.\nUsing Math.random(), which is NOT cryptographically strong!'
|
||||
};
|
||||
|
||||
// Protected settings object
|
||||
var config = {};
|
||||
|
||||
/** @expose **/
|
||||
exports.getConfig = function(){
|
||||
return {
|
||||
'bits': config.bits,
|
||||
'unsafePRNG': config.unsafePRNG
|
||||
};
|
||||
};
|
||||
|
||||
function init(bits){
|
||||
if(bits && (typeof bits !== 'number' || bits%1 !== 0 || bits<defaults.minBits || bits>defaults.maxBits)){
|
||||
throw new Error('Number of bits must be an integer between ' + defaults.minBits + ' and ' + defaults.maxBits + ', inclusive.')
|
||||
}
|
||||
|
||||
config.radix = defaults.radix;
|
||||
config.bits = bits || defaults.bits;
|
||||
config.size = Math.pow(2, config.bits);
|
||||
config.max = config.size - 1;
|
||||
|
||||
// Construct the exp and log tables for multiplication.
|
||||
var logs = [], exps = [], x = 1, primitive = defaults.primitivePolynomials[config.bits];
|
||||
for(var i=0; i<config.size; i++){
|
||||
exps[i] = x;
|
||||
logs[x] = i;
|
||||
x <<= 1;
|
||||
if(x >= config.size){
|
||||
x ^= primitive;
|
||||
x &= config.max;
|
||||
}
|
||||
}
|
||||
|
||||
config.logs = logs;
|
||||
config.exps = exps;
|
||||
};
|
||||
|
||||
/** @expose **/
|
||||
exports.init = init;
|
||||
|
||||
function isInited(){
|
||||
if(!config.bits || !config.size || !config.max || !config.logs || !config.exps || config.logs.length !== config.size || config.exps.length !== config.size){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Returns a pseudo-random number generator of the form function(bits){}
|
||||
// which should output a random string of 1's and 0's of length `bits`
|
||||
function getRNG(){
|
||||
var randomBits, crypto;
|
||||
|
||||
function construct(bits, arr, radix, size){
|
||||
var str = '',
|
||||
i = 0,
|
||||
len = arr.length-1;
|
||||
while( i<len || (str.length < bits) ){
|
||||
str += padLeft(parseInt(arr[i], radix).toString(2), size);
|
||||
i++;
|
||||
}
|
||||
str = str.substr(-bits);
|
||||
if( (str.match(/0/g)||[]).length === str.length){ // all zeros?
|
||||
return null;
|
||||
}else{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// node.js crypto.randomBytes()
|
||||
if(typeof require === 'function' && (crypto=require('crypto')) && (randomBits=crypto['randomBytes'])){
|
||||
return function(bits){
|
||||
var bytes = Math.ceil(bits/8),
|
||||
str = null;
|
||||
|
||||
while( str === null ){
|
||||
str = construct(bits, randomBits(bytes).toString('hex'), 16, 4);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// browsers with window.crypto.getRandomValues()
|
||||
if(global['crypto'] && typeof global['crypto']['getRandomValues'] === 'function' && typeof global['Uint32Array'] === 'function'){
|
||||
crypto = global['crypto'];
|
||||
return function(bits){
|
||||
var elems = Math.ceil(bits/32),
|
||||
str = null,
|
||||
arr = new global['Uint32Array'](elems);
|
||||
|
||||
while( str === null ){
|
||||
crypto['getRandomValues'](arr);
|
||||
str = construct(bits, arr, 10, 32);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// A totally insecure RNG!!! (except in Safari)
|
||||
// Will produce a warning every time it is called.
|
||||
config.unsafePRNG = true;
|
||||
warn();
|
||||
|
||||
var bitsPerNum = 32;
|
||||
var max = Math.pow(2,bitsPerNum)-1;
|
||||
return function(bits){
|
||||
var elems = Math.ceil(bits/bitsPerNum);
|
||||
var arr = [], str=null;
|
||||
while(str===null){
|
||||
for(var i=0; i<elems; i++){
|
||||
arr[i] = Math.floor(Math.random() * max + 1);
|
||||
}
|
||||
str = construct(bits, arr, 10, bitsPerNum);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
};
|
||||
|
||||
// Warn about using insecure rng.
|
||||
// Called when Math.random() is being used.
|
||||
function warn(){
|
||||
global['console']['warn'](defaults.warning);
|
||||
if(typeof global['alert'] === 'function' && config.alert){
|
||||
global['alert'](defaults.warning);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the PRNG to use. If no RNG function is supplied, pick a default using getRNG()
|
||||
/** @expose **/
|
||||
exports.setRNG = function(rng, alert){
|
||||
if(!isInited()){
|
||||
this.init();
|
||||
}
|
||||
config.unsafePRNG=false;
|
||||
rng = rng || getRNG();
|
||||
|
||||
// test the RNG (5 times)
|
||||
if(typeof rng !== 'function' || typeof rng(config.bits) !== 'string' || !parseInt(rng(config.bits),2) || rng(config.bits).length > config.bits || rng(config.bits).length < config.bits){
|
||||
throw new Error("Random number generator is invalid. Supply an RNG of the form function(bits){} that returns a string containing 'bits' number of random 1's and 0's.")
|
||||
}else{
|
||||
config.rng = rng;
|
||||
}
|
||||
config.alert = !!alert;
|
||||
|
||||
return !!config.unsafePRNG;
|
||||
};
|
||||
|
||||
function isSetRNG(){
|
||||
return typeof config.rng === 'function';
|
||||
};
|
||||
|
||||
// Generates a random bits-length number string using the PRNG
|
||||
/** @expose **/
|
||||
exports.random = function(bits){
|
||||
if(!isSetRNG()){
|
||||
this.setRNG();
|
||||
}
|
||||
|
||||
if(typeof bits !== 'number' || bits%1 !== 0 || bits < 2){
|
||||
throw new Error('Number of bits must be an integer greater than 1.')
|
||||
}
|
||||
|
||||
if(config.unsafePRNG){
|
||||
warn();
|
||||
}
|
||||
return bin2hex(config.rng(bits));
|
||||
}
|
||||
|
||||
// Divides a `secret` number String str expressed in radix `inputRadix` (optional, default 16)
|
||||
// into `numShares` shares, each expressed in radix `outputRadix` (optional, default to `inputRadix`),
|
||||
// requiring `threshold` number of shares to reconstruct the secret.
|
||||
// Optionally, zero-pads the secret to a length that is a multiple of padLength before sharing.
|
||||
/** @expose **/
|
||||
exports.share = function(secret, numShares, threshold, padLength, withoutPrefix){
|
||||
if(!isInited()){
|
||||
this.init();
|
||||
}
|
||||
if(!isSetRNG()){
|
||||
this.setRNG();
|
||||
}
|
||||
|
||||
padLength = padLength || 0;
|
||||
|
||||
if(typeof secret !== 'string'){
|
||||
throw new Error('Secret must be a string.');
|
||||
}
|
||||
if(typeof numShares !== 'number' || numShares%1 !== 0 || numShares < 2){
|
||||
throw new Error('Number of shares must be an integer between 2 and 2^bits-1 (' + config.max + '), inclusive.')
|
||||
}
|
||||
if(numShares > config.max){
|
||||
var neededBits = Math.ceil(Math.log(numShares +1)/Math.LN2);
|
||||
throw new Error('Number of shares must be an integer between 2 and 2^bits-1 (' + config.max + '), inclusive. To create ' + numShares + ' shares, use at least ' + neededBits + ' bits.')
|
||||
}
|
||||
if(typeof threshold !== 'number' || threshold%1 !== 0 || threshold < 2){
|
||||
throw new Error('Threshold number of shares must be an integer between 2 and 2^bits-1 (' + config.max + '), inclusive.');
|
||||
}
|
||||
if(threshold > config.max){
|
||||
var neededBits = Math.ceil(Math.log(threshold +1)/Math.LN2);
|
||||
throw new Error('Threshold number of shares must be an integer between 2 and 2^bits-1 (' + config.max + '), inclusive. To use a threshold of ' + threshold + ', use at least ' + neededBits + ' bits.');
|
||||
}
|
||||
if(typeof padLength !== 'number' || padLength%1 !== 0 ){
|
||||
throw new Error('Zero-pad length must be an integer greater than 1.');
|
||||
}
|
||||
|
||||
if(config.unsafePRNG){
|
||||
warn();
|
||||
}
|
||||
|
||||
secret = '1' + hex2bin(secret); // append a 1 so that we can preserve the correct number of leading zeros in our secret
|
||||
secret = split(secret, padLength);
|
||||
var x = new Array(numShares), y = new Array(numShares);
|
||||
for(var i=0, len = secret.length; i<len; i++){
|
||||
var subShares = this._getShares(secret[i], numShares, threshold);
|
||||
for(var j=0; j<numShares; j++){
|
||||
x[j] = x[j] || subShares[j].x.toString(config.radix);
|
||||
y[j] = padLeft(subShares[j].y.toString(2)) + (y[j] ? y[j] : '');
|
||||
}
|
||||
}
|
||||
var padding = config.max.toString(config.radix).length;
|
||||
if(withoutPrefix){
|
||||
for(var i=0; i<numShares; i++){
|
||||
x[i] = bin2hex(y[i]);
|
||||
}
|
||||
}else{
|
||||
for(var i=0; i<numShares; i++){
|
||||
x[i] = config.bits.toString(36).toUpperCase() + padLeft(x[i],padding) + bin2hex(y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return x;
|
||||
};
|
||||
|
||||
// This is the basic polynomial generation and evaluation function
|
||||
// for a `config.bits`-length secret (NOT an arbitrary length)
|
||||
// Note: no error-checking at this stage! If `secrets` is NOT
|
||||
// a NUMBER less than 2^bits-1, the output will be incorrect!
|
||||
/** @expose **/
|
||||
exports._getShares = function(secret, numShares, threshold){
|
||||
var shares = [];
|
||||
var coeffs = [secret];
|
||||
|
||||
for(var i=1; i<threshold; i++){
|
||||
coeffs[i] = parseInt(config.rng(config.bits),2);
|
||||
}
|
||||
for(var i=1, len = numShares+1; i<len; i++){
|
||||
shares[i-1] = {
|
||||
x: i,
|
||||
y: horner(i, coeffs)
|
||||
}
|
||||
}
|
||||
return shares;
|
||||
};
|
||||
|
||||
// Polynomial evaluation at `x` using Horner's Method
|
||||
// TODO: this can possibly be sped up using other methods
|
||||
// NOTE: fx=fx * x + coeff[i] -> exp(log(fx) + log(x)) + coeff[i],
|
||||
// so if fx===0, just set fx to coeff[i] because
|
||||
// using the exp/log form will result in incorrect value
|
||||
function horner(x, coeffs){
|
||||
var logx = config.logs[x];
|
||||
var fx = 0;
|
||||
for(var i=coeffs.length-1; i>=0; i--){
|
||||
if(fx === 0){
|
||||
fx = coeffs[i];
|
||||
continue;
|
||||
}
|
||||
fx = config.exps[ (logx + config.logs[fx]) % config.max ] ^ coeffs[i];
|
||||
}
|
||||
return fx;
|
||||
};
|
||||
|
||||
function inArray(arr,val){
|
||||
for(var i = 0,len=arr.length; i < len; i++) {
|
||||
if(arr[i] === val){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function processShare(share){
|
||||
|
||||
var bits = parseInt(share[0], 36);
|
||||
if(bits && (typeof bits !== 'number' || bits%1 !== 0 || bits<defaults.minBits || bits>defaults.maxBits)){
|
||||
throw new Error('Number of bits must be an integer between ' + defaults.minBits + ' and ' + defaults.maxBits + ', inclusive.')
|
||||
}
|
||||
|
||||
var max = Math.pow(2, bits) - 1;
|
||||
var idLength = max.toString(config.radix).length;
|
||||
|
||||
var id = parseInt(share.substr(1, idLength), config.radix);
|
||||
if(typeof id !== 'number' || id%1 !== 0 || id<1 || id>max){
|
||||
throw new Error('Share id must be an integer between 1 and ' + config.max + ', inclusive.');
|
||||
}
|
||||
share = share.substr(idLength + 1);
|
||||
if(!share.length){
|
||||
throw new Error('Invalid share: zero-length share.')
|
||||
}
|
||||
return {
|
||||
'bits': bits,
|
||||
'id': id,
|
||||
'value': share
|
||||
};
|
||||
};
|
||||
|
||||
/** @expose **/
|
||||
exports._processShare = processShare;
|
||||
|
||||
// Protected method that evaluates the Lagrange interpolation
|
||||
// polynomial at x=`at` for individual config.bits-length
|
||||
// segments of each share in the `shares` Array.
|
||||
// Each share is expressed in base `inputRadix`. The output
|
||||
// is expressed in base `outputRadix'
|
||||
function combine(at, shares){
|
||||
var setBits, share, x = [], y = [], result = '', idx;
|
||||
|
||||
for(var i=0, len = shares.length; i<len; i++){
|
||||
share = processShare(shares[i]);
|
||||
if(typeof setBits === 'undefined'){
|
||||
setBits = share['bits'];
|
||||
}else if(share['bits'] !== setBits){
|
||||
throw new Error('Mismatched shares: Different bit settings.')
|
||||
}
|
||||
|
||||
if(config.bits !== setBits){
|
||||
init(setBits);
|
||||
}
|
||||
|
||||
if(inArray(x, share['id'])){ // repeated x value?
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = x.push(share['id']) - 1;
|
||||
share = split(hex2bin(share['value']));
|
||||
for(var j=0, len2 = share.length; j<len2; j++){
|
||||
y[j] = y[j] || [];
|
||||
y[j][idx] = share[j];
|
||||
}
|
||||
}
|
||||
|
||||
for(var i=0, len=y.length; i<len; i++){
|
||||
result = padLeft(lagrange(at, x, y[i]).toString(2)) + result;
|
||||
}
|
||||
|
||||
if(at===0){// reconstructing the secret
|
||||
var idx = result.indexOf('1'); //find the first 1
|
||||
return bin2hex(result.slice(idx+1));
|
||||
}else{// generating a new share
|
||||
return bin2hex(result);
|
||||
}
|
||||
};
|
||||
|
||||
// Combine `shares` Array into the original secret
|
||||
/** @expose **/
|
||||
exports.combine = function(shares){
|
||||
return combine(0, shares);
|
||||
};
|
||||
|
||||
// Generate a new share with id `id` (a number between 1 and 2^bits-1)
|
||||
// `id` can be a Number or a String in the default radix (16)
|
||||
/** @expose **/
|
||||
exports.newShare = function(id, shares){
|
||||
if(typeof id === 'string'){
|
||||
id = parseInt(id, config.radix);
|
||||
}
|
||||
|
||||
var share = processShare(shares[0]);
|
||||
var max = Math.pow(2, share['bits']) - 1;
|
||||
|
||||
if(typeof id !== 'number' || id%1 !== 0 || id<1 || id>max){
|
||||
throw new Error('Share id must be an integer between 1 and ' + config.max + ', inclusive.');
|
||||
}
|
||||
|
||||
var padding = max.toString(config.radix).length;
|
||||
return config.bits.toString(36).toUpperCase() + padLeft(id.toString(config.radix), padding) + combine(id, shares);
|
||||
};
|
||||
|
||||
// Evaluate the Lagrange interpolation polynomial at x = `at`
|
||||
// using x and y Arrays that are of the same length, with
|
||||
// corresponding elements constituting points on the polynomial.
|
||||
function lagrange(at, x, y){
|
||||
var sum = 0,
|
||||
product,
|
||||
i, j;
|
||||
|
||||
for(var i=0, len = x.length; i<len; i++){
|
||||
if(!y[i]){
|
||||
continue;
|
||||
}
|
||||
|
||||
product = config.logs[y[i]];
|
||||
for(var j=0; j<len; j++){
|
||||
if(i === j){ continue; }
|
||||
if(at === x[j]){ // happens when computing a share that is in the list of shares used to compute it
|
||||
product = -1; // fix for a zero product term, after which the sum should be sum^0 = sum, not sum^1
|
||||
break;
|
||||
}
|
||||
product = ( product + config.logs[at ^ x[j]] - config.logs[x[i] ^ x[j]] + config.max/* to make sure it's not negative */ ) % config.max;
|
||||
}
|
||||
|
||||
sum = product === -1 ? sum : sum ^ config.exps[product]; // though exps[-1]= undefined and undefined ^ anything = anything in chrome, this behavior may not hold everywhere, so do the check
|
||||
}
|
||||
return sum;
|
||||
};
|
||||
|
||||
/** @expose **/
|
||||
exports._lagrange = lagrange;
|
||||
|
||||
// Splits a number string `bits`-length segments, after first
|
||||
// optionally zero-padding it to a length that is a multiple of `padLength.
|
||||
// Returns array of integers (each less than 2^bits-1), with each element
|
||||
// representing a `bits`-length segment of the input string from right to left,
|
||||
// i.e. parts[0] represents the right-most `bits`-length segment of the input string.
|
||||
function split(str, padLength){
|
||||
if(padLength){
|
||||
str = padLeft(str, padLength)
|
||||
}
|
||||
var parts = [];
|
||||
for(var i=str.length; i>config.bits; i-=config.bits){
|
||||
parts.push(parseInt(str.slice(i-config.bits, i), 2));
|
||||
}
|
||||
parts.push(parseInt(str.slice(0, i), 2));
|
||||
return parts;
|
||||
};
|
||||
|
||||
// Pads a string `str` with zeros on the left so that its length is a multiple of `bits`
|
||||
function padLeft(str, bits){
|
||||
bits = bits || config.bits
|
||||
var missing = str.length % bits;
|
||||
return (missing ? new Array(bits - missing + 1).join('0') : '') + str;
|
||||
};
|
||||
|
||||
function hex2bin(str){
|
||||
var bin = '', num;
|
||||
for(var i=str.length - 1; i>=0; i--){
|
||||
num = parseInt(str[i], 16)
|
||||
if(isNaN(num)){
|
||||
throw new Error('Invalid hex character.')
|
||||
}
|
||||
bin = padLeft(num.toString(2), 4) + bin;
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
function bin2hex(str){
|
||||
var hex = '', num;
|
||||
str = padLeft(str, 4);
|
||||
for(var i=str.length; i>=4; i-=4){
|
||||
num = parseInt(str.slice(i-4, i), 2);
|
||||
if(isNaN(num)){
|
||||
throw new Error('Invalid binary character.')
|
||||
}
|
||||
hex = num.toString(16) + hex;
|
||||
}
|
||||
return hex;
|
||||
}
|
||||
|
||||
// Converts a given UTF16 character string to the HEX representation.
|
||||
// Each character of the input string is represented by
|
||||
// `bytesPerChar` bytes in the output string.
|
||||
/** @expose **/
|
||||
exports.str2hex = function(str, bytesPerChar){
|
||||
if(typeof str !== 'string'){
|
||||
throw new Error('Input must be a character string.');
|
||||
}
|
||||
bytesPerChar = bytesPerChar || defaults.bytesPerChar;
|
||||
|
||||
if(typeof bytesPerChar !== 'number' || bytesPerChar%1 !== 0 || bytesPerChar<1 || bytesPerChar > defaults.maxBytesPerChar){
|
||||
throw new Error('Bytes per character must be an integer between 1 and ' + defaults.maxBytesPerChar + ', inclusive.')
|
||||
}
|
||||
|
||||
var hexChars = 2*bytesPerChar;
|
||||
var max = Math.pow(16, hexChars) - 1;
|
||||
var out = '', num;
|
||||
for(var i=0, len=str.length; i<len; i++){
|
||||
num = str[i].charCodeAt();
|
||||
if(isNaN(num)){
|
||||
throw new Error('Invalid character: ' + str[i]);
|
||||
}else if(num > max){
|
||||
var neededBytes = Math.ceil(Math.log(num+1)/Math.log(256));
|
||||
throw new Error('Invalid character code (' + num +'). Maximum allowable is 256^bytes-1 (' + max + '). To convert this character, use at least ' + neededBytes + ' bytes.')
|
||||
}else{
|
||||
out = padLeft(num.toString(16), hexChars) + out;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
// Converts a given HEX number string to a UTF16 character string.
|
||||
/** @expose **/
|
||||
exports.hex2str = function(str, bytesPerChar){
|
||||
if(typeof str !== 'string'){
|
||||
throw new Error('Input must be a hexadecimal string.');
|
||||
}
|
||||
bytesPerChar = bytesPerChar || defaults.bytesPerChar;
|
||||
|
||||
if(typeof bytesPerChar !== 'number' || bytesPerChar%1 !== 0 || bytesPerChar<1 || bytesPerChar > defaults.maxBytesPerChar){
|
||||
throw new Error('Bytes per character must be an integer between 1 and ' + defaults.maxBytesPerChar + ', inclusive.')
|
||||
}
|
||||
|
||||
var hexChars = 2*bytesPerChar;
|
||||
var out = '';
|
||||
str = padLeft(str, hexChars);
|
||||
for(var i=0, len = str.length; i<len; i+=hexChars){
|
||||
out = String.fromCharCode(parseInt(str.slice(i, i+hexChars),16)) + out;
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
// by default, initialize without an RNG
|
||||
exports.init();
|
||||
})(typeof module !== 'undefined' && module['exports'] ? module['exports'] : (window['secrets'] = {}), typeof GLOBAL !== 'undefined' ? GLOBAL : window );
|
Loading…
Reference in a new issue