1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-04 00:53:36 +02:00

Compare commits

...

10 Commits

Author SHA1 Message Date
m2049r
f0523c403c bump version 2019-03-19 19:34:04 +01:00
m2049r
966ed23b87 enable ledger again 2019-03-19 19:32:38 +01:00
m2049r
95f2ca74a6 clean code (#555) 2019-03-10 22:00:57 +01:00
m2049r
81d94478f2 update wallet api (#554) 2019-03-10 21:49:57 +01:00
el00ruobuob
16ff779ebc New strings & help update to FR (#552) 2019-03-09 21:58:10 +01:00
m2049r
6b7bb164f4 v1.11.3 (#550) 2019-03-09 00:07:37 +01:00
m2049r
da1d4ea1bf convert ledger seed dialog (#549) 2019-03-09 00:02:58 +01:00
m2049r
d5a967f690 upgrade gradle version (#548) 2019-03-06 16:46:52 +01:00
m2049r
de8de02f9f disable ledger support (#547) 2019-03-05 23:35:11 +01:00
m2049r
06456e33e4 v1.11.1 (#546)
for use with b087cbf995
2019-03-05 21:59:19 +01:00
41 changed files with 2744 additions and 60 deletions

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 28
versionCode 170
versionName "1.11.0 'Chernushka'"
versionCode 175
versionName "1.11.5 'Chernushka'"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
@@ -115,6 +115,10 @@ dependencies {
implementation 'org.slf4j:slf4j-nop:1.7.25'
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
// https://mvnrepository.com/artifact/com.github.aelstad/keccakj
implementation 'com.github.aelstad:keccakj:1.1.0'
testImplementation "junit:junit:$rootProject.ext.junitVersion"
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
testImplementation "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"

View File

@@ -16,6 +16,7 @@
package com.m2049r.xmrwallet;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -33,6 +34,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.LinearLayout;
@@ -45,6 +47,7 @@ import com.m2049r.xmrwallet.util.FingerprintHelper;
import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.KeyStoreHelper;
import com.m2049r.xmrwallet.util.RestoreHeight;
import com.m2049r.xmrwallet.util.ledger.Monero;
import com.m2049r.xmrwallet.widget.Toolbar;
import com.nulabinc.zxcvbn.Strength;
import com.nulabinc.zxcvbn.Zxcvbn;
@@ -240,9 +243,7 @@ public class GenerateFragment extends Fragment {
}
});
etWalletAddress.setVisibility(View.VISIBLE);
etWalletAddress.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener()
{
etWalletAddress.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_NEXT)) {
@@ -274,9 +275,7 @@ public class GenerateFragment extends Fragment {
}
if (type.equals(TYPE_KEY)) {
etWalletSpendKey.setVisibility(View.VISIBLE);
etWalletSpendKey.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener()
{
etWalletSpendKey.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
|| (actionId == EditorInfo.IME_ACTION_NEXT)) {
@@ -303,9 +302,7 @@ public class GenerateFragment extends Fragment {
}
});
}
bGenerate.setOnClickListener(new View.OnClickListener()
{
bGenerate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.hideKeyboard(getActivity());
@@ -616,4 +613,80 @@ public class GenerateFragment extends Fragment {
}
super.onCreateOptionsMenu(menu, inflater);
}
AlertDialog ledgerDialog = null;
public void convertLedgerSeed() {
if (ledgerDialog != null) return;
final Activity activity = getActivity();
View promptsView = getLayoutInflater().inflate(R.layout.prompt_ledger_seed, null);
android.app.AlertDialog.Builder alertDialogBuilder = new android.app.AlertDialog.Builder(activity);
alertDialogBuilder.setView(promptsView);
final TextInputLayout etSeed = promptsView.findViewById(R.id.etSeed);
final TextInputLayout etPassphrase = promptsView.findViewById(R.id.etPassphrase);
etSeed.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (etSeed.getError() != null) {
etSeed.setError(null);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
alertDialogBuilder
.setCancelable(false)
.setPositiveButton(getString(R.string.label_ok), null)
.setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Helper.hideKeyboardAlways(activity);
etWalletMnemonic.getEditText().getText().clear();
dialog.cancel();
ledgerDialog = null;
}
});
ledgerDialog = alertDialogBuilder.create();
ledgerDialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String ledgerSeed = etSeed.getEditText().getText().toString();
String ledgerPassphrase = etPassphrase.getEditText().getText().toString();
String moneroSeed = Monero.convert(ledgerSeed, ledgerPassphrase);
if (moneroSeed != null) {
etWalletMnemonic.getEditText().setText(moneroSeed);
ledgerDialog.dismiss();
ledgerDialog = null;
} else {
etSeed.setError(getString(R.string.bad_ledger_seed));
}
}
});
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
ledgerDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
ledgerDialog.show();
}
}

View File

@@ -33,6 +33,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ImageButton;
@@ -620,6 +621,11 @@ public class GenerateReviewFragment extends Fragment {
return false;
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
openDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
return openDialog;
}

View File

@@ -1229,6 +1229,12 @@ public class LoginActivity extends BaseActivity
case R.id.action_language:
onChangeLocale();
return true;
case R.id.action_ledger_seed:
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if (f instanceof GenerateFragment) {
((GenerateFragment) f).convertLedgerSeed();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
@@ -1361,30 +1367,31 @@ public class LoginActivity extends BaseActivity
};
private void connectLedger(UsbManager usbManager, final UsbDevice usbDevice) {
try {
Ledger.connect(usbManager, usbDevice);
registerDetachReceiver();
onLedgerAction();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
} catch (IOException ex) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.open_wallet_ledger_missing),
Toast.LENGTH_SHORT)
.show();
}
});
}
if (Ledger.ENABLED)
try {
Ledger.connect(usbManager, usbDevice);
registerDetachReceiver();
onLedgerAction();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.toast_ledger_attached, usbDevice.getProductName()),
Toast.LENGTH_SHORT)
.show();
}
});
} catch (IOException ex) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,
getString(R.string.open_wallet_ledger_missing),
Toast.LENGTH_SHORT)
.show();
}
});
}
}
@Override

View File

@@ -32,6 +32,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
@@ -505,6 +506,10 @@ public class NodeFragment extends Fragment
});
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
editDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
etNodePass.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

View File

@@ -62,9 +62,6 @@ public class ProgressDialog extends AlertDialog {
pbBar = view.findViewById(R.id.pbBar);
tvProgress = view.findViewById(R.id.tvProgress);
setView(view);
//setTitle("blabla");
//super.setMessage("bubbu");
// view.invalidate();
setIndeterminate(indeterminate);
if (maxValue > 0) {
setMax(maxValue);

View File

@@ -27,11 +27,13 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.data.TxData;
import com.m2049r.xmrwallet.data.TxDataBtc;
@@ -435,6 +437,11 @@ public class SendBtcConfirmWizardFragment extends SendWizardFragment implements
return false;
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
passwordDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
passwordDialog.show();
}

View File

@@ -27,10 +27,12 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.data.TxData;
import com.m2049r.xmrwallet.model.PendingTransaction;
@@ -322,6 +324,11 @@ public class SendConfirmWizardFragment extends SendWizardFragment implements Sen
return false;
}
});
// set FLAG_SECURE to prevent screenshots in Release Mode
if (!(BuildConfig.DEBUG && BuildConfig.FLAVOR_type.equals("alpha"))) {
passwordDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}
passwordDialog.show();
}

View File

@@ -34,6 +34,7 @@ import java.io.IOException;
import timber.log.Timber;
public class Ledger {
static final public boolean ENABLED = true;
// 5:20 is same as wallet2.cpp::restore()
static public final int LOOKAHEAD_ACCOUNTS = 5;
static public final int LOOKAHEAD_SUBADDRESSES = 20;
@@ -44,6 +45,7 @@ public class Ledger {
public static final int OK[] = {SW_OK};
public static UsbDevice findDevice(UsbManager usbManager) {
if (!ENABLED) return null;
return BTChipTransportAndroidHID.getDevice(usbManager);
}

View File

@@ -0,0 +1,81 @@
/*
* Based on
* https://stackoverflow.com/a/19943894
*
* Curve parameters from
* https://en.bitcoin.it/wiki/Secp256k1
*
* Copyright (c) 2019 m2049r
* Copyright (c) 2013 ChiaraHsieh
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.util.ledger;
import java.math.BigInteger;
import java.security.spec.ECPoint;
public class ECsecp256k1 {
static private final BigInteger TWO = new BigInteger("2");
static private final BigInteger THREE = new BigInteger("3");
static public final BigInteger p = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
static public final BigInteger a = new BigInteger("0000000000000000000000000000000000000000000000000000000000000000", 16);
static public final BigInteger b = new BigInteger("0000000000000000000000000000000000000000000000000000000000000007", 16);
static public final BigInteger n = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16);
static public final ECPoint G = new ECPoint(
new BigInteger("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16),
new BigInteger("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16));
public static ECPoint scalmult(BigInteger kin, ECPoint P) {
ECPoint R = ECPoint.POINT_INFINITY, S = P;
BigInteger k = kin.mod(n); // not necessary b/c that's how curves work
int length = k.bitLength();
byte[] binarray = new byte[length];
for (int i = 0; i <= length - 1; i++) {
binarray[i] = k.mod(TWO).byteValue();
k = k.divide(TWO);
}
for (int i = length - 1; i >= 0; i--) {
// i should start at length-1 not -2 because the MSB of binary may not be 1
R = doublePoint(R);
if (binarray[i] == 1)
R = addPoint(R, S);
}
return R;
}
public static ECPoint addPoint(ECPoint r, ECPoint s) {
if (r.equals(s))
return doublePoint(r);
else if (r.equals(ECPoint.POINT_INFINITY))
return s;
else if (s.equals(ECPoint.POINT_INFINITY))
return r;
BigInteger slope = (r.getAffineY().subtract(s.getAffineY()))
.multiply(r.getAffineX().subtract(s.getAffineX()).modInverse(p));
BigInteger Xout = (slope.modPow(TWO, p).subtract(r.getAffineX())).subtract(s.getAffineX()).mod(p);
BigInteger Yout = s.getAffineY().negate().add(slope.multiply(s.getAffineX().subtract(Xout))).mod(p);
return new ECPoint(Xout, Yout);
}
public static ECPoint doublePoint(ECPoint r) {
if (r.equals(ECPoint.POINT_INFINITY))
return r;
BigInteger slope = (r.getAffineX().pow(2)).multiply(THREE).add(a)
.multiply((r.getAffineY().multiply(TWO)).modInverse(p));
BigInteger Xout = slope.pow(2).subtract(r.getAffineX().multiply(TWO)).mod(p);
BigInteger Yout = (r.getAffineY().negate()).add(slope.multiply(r.getAffineX().subtract(Xout))).mod(p);
return new ECPoint(Xout, Yout);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
package com.theromus.sha;
import static com.theromus.utils.HexUtils.leftRotate64;
import static com.theromus.utils.HexUtils.convertToUint;
import static com.theromus.utils.HexUtils.convertFromLittleEndianTo64;
import static com.theromus.utils.HexUtils.convertFrom64ToLittleEndian;
import static java.lang.Math.min;
import static java.lang.System.arraycopy;
import static java.util.Arrays.fill;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
/**
* Keccak implementation.
*
* @author romus
*/
public class Keccak {
private static BigInteger BIT_64 = new BigInteger("18446744073709551615");
/**
* Do hash.
*
* @param message input data
* @param parameter keccak param
* @return byte-array result
*/
public byte[] getHash(final byte[] message, final Parameters parameter) {
int[] uState = new int[200];
int[] uMessage = convertToUint(message);
int rateInBytes = parameter.getRate() / 8;
int blockSize = 0;
int inputOffset = 0;
// Absorbing phase
while (inputOffset < uMessage.length) {
blockSize = min(uMessage.length - inputOffset, rateInBytes);
for (int i = 0; i < blockSize; i++) {
uState[i] = uState[i] ^ uMessage[i + inputOffset];
}
inputOffset = inputOffset + blockSize;
if (blockSize == rateInBytes) {
doKeccakf(uState);
blockSize = 0;
}
}
// Padding phase
uState[blockSize] = uState[blockSize] ^ parameter.getD();
if ((parameter.getD() & 0x80) != 0 && blockSize == (rateInBytes - 1)) {
doKeccakf(uState);
}
uState[rateInBytes - 1] = uState[rateInBytes - 1] ^ 0x80;
doKeccakf(uState);
// Squeezing phase
ByteArrayOutputStream byteResults = new ByteArrayOutputStream();
int tOutputLen = parameter.getOutputLen() / 8;
while (tOutputLen > 0) {
blockSize = min(tOutputLen, rateInBytes);
for (int i = 0; i < blockSize; i++) {
byteResults.write((byte) uState[i]);
}
tOutputLen -= blockSize;
if (tOutputLen > 0) {
doKeccakf(uState);
}
}
return byteResults.toByteArray();
}
private void doKeccakf(final int[] uState) {
BigInteger[][] lState = new BigInteger[5][5];
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
int[] data = new int[8];
arraycopy(uState, 8 * (i + 5 * j), data, 0, data.length);
lState[i][j] = convertFromLittleEndianTo64(data);
}
}
roundB(lState);
fill(uState, 0);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
int[] data = convertFrom64ToLittleEndian(lState[i][j]);
arraycopy(data, 0, uState, 8 * (i + 5 * j), data.length);
}
}
}
/**
* Permutation on the given state.
*
* @param state state
*/
private void roundB(final BigInteger[][] state) {
int LFSRstate = 1;
for (int round = 0; round < 24; round++) {
BigInteger[] C = new BigInteger[5];
BigInteger[] D = new BigInteger[5];
// θ step
for (int i = 0; i < 5; i++) {
C[i] = state[i][0].xor(state[i][1]).xor(state[i][2]).xor(state[i][3]).xor(state[i][4]);
}
for (int i = 0; i < 5; i++) {
D[i] = C[(i + 4) % 5].xor(leftRotate64(C[(i + 1) % 5], 1));
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
state[i][j] = state[i][j].xor(D[i]);
}
}
//ρ and π steps
int x = 1, y = 0;
BigInteger current = state[x][y];
for (int i = 0; i < 24; i++) {
int tX = x;
x = y;
y = (2 * tX + 3 * y) % 5;
BigInteger shiftValue = current;
current = state[x][y];
state[x][y] = leftRotate64(shiftValue, (i + 1) * (i + 2) / 2);
}
//χ step
for (int j = 0; j < 5; j++) {
BigInteger[] t = new BigInteger[5];
for (int i = 0; i < 5; i++) {
t[i] = state[i][j];
}
for (int i = 0; i < 5; i++) {
// ~t[(i + 1) % 5]
BigInteger invertVal = t[(i + 1) % 5].xor(BIT_64);
// t[i] ^ ((~t[(i + 1) % 5]) & t[(i + 2) % 5])
state[i][j] = t[i].xor(invertVal.and(t[(i + 2) % 5]));
}
}
//ι step
for (int i = 0; i < 7; i++) {
LFSRstate = ((LFSRstate << 1) ^ ((LFSRstate >> 7) * 0x71)) % 256;
// pow(2, i) - 1
int bitPosition = (1 << i) - 1;
if ((LFSRstate & 2) != 0) {
state[0][0] = state[0][0].xor(new BigInteger("1").shiftLeft(bitPosition));
}
}
}
}
}

View File

@@ -0,0 +1,51 @@
package com.theromus.sha;
/**
* The parameters defining the standard FIPS 202.
*
* @author romus
*/
public enum Parameters {
KECCAK_224 (1152, 0x01, 224),
KECCAK_256 (1088, 0x01, 256),
KECCAK_384 (832, 0x01, 384),
KECCAK_512 (576, 0x01, 512),
SHA3_224 (1152, 0x06, 224),
SHA3_256 (1088, 0x06, 256),
SHA3_384 (832, 0x06, 384),
SHA3_512 (576, 0x06, 512),
SHAKE128 (1344, 0x1F, 256),
SHAKE256 (1088, 0x1F, 512);
private final int rate;
/**
* Delimited suffix.
*/
public final int d;
/**
* Output length (bits).
*/
public final int outputLen;
Parameters(int rate, int d, int outputLen) {
this.rate = rate;
this.d = d;
this.outputLen = outputLen;
}
public int getRate() {
return rate;
}
public int getD() {
return d;
}
public int getOutputLen() {
return outputLen;
}
}

View File

@@ -0,0 +1,97 @@
package com.theromus.utils;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
/**
* Hex-utils.
*
* @author romus
*/
public class HexUtils {
private static final byte[] ENCODE_BYTE_TABLE = {
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
};
/**
* Convert byte array to unsigned array.
*
* @param data byte array
* @return unsigned array
*/
public static int[] convertToUint(final byte[] data) {
int[] converted = new int[data.length];
for (int i = 0; i < data.length; i++) {
converted[i] = data[i] & 0xFF;
}
return converted;
}
/**
* Convert LE to 64-bit value (unsigned long).
*
* @param data data
* @return 64-bit value (unsigned long)
*/
public static BigInteger convertFromLittleEndianTo64(final int[] data) {
BigInteger uLong = new BigInteger("0");
for (int i = 0; i < 8; i++) {
uLong = uLong.add(new BigInteger(Integer.toString(data[i])).shiftLeft(8 * i));
}
return uLong;
}
/**
* Convert 64-bit (unsigned long) value to LE.
*
* @param uLong 64-bit value (unsigned long)
* @return LE
*/
public static int[] convertFrom64ToLittleEndian(final BigInteger uLong) {
int[] data = new int[8];
BigInteger mod256 = new BigInteger("256");
for (int i = 0; i < 8; i++) {
data[i] = uLong.shiftRight((8 * i)).mod(mod256).intValue();
}
return data;
}
/**
* Bitwise rotate left.
*
* @param value unsigned long value
* @param rotate rotate left
* @return result
*/
public static BigInteger leftRotate64(final BigInteger value, final int rotate) {
BigInteger lp = value.shiftRight(64 - (rotate % 64));
BigInteger rp = value.shiftLeft(rotate % 64);
return lp.add(rp).mod(new BigInteger("18446744073709551616"));
}
/**
* Convert bytes to string.
*
* @param data bytes array
* @return string
*/
public static String convertBytesToString(final byte[] data) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < data.length; i++) {
int uVal = data[i] & 0xFF;
buffer.write(ENCODE_BYTE_TABLE[(uVal >>> 4)]);
buffer.write(ENCODE_BYTE_TABLE[uVal & 0xF]);
}
return new String(buffer.toByteArray());
}
}

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
style="@style/MoneroLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:labelFor="@+id/etSeed"
android:text="@string/menu_ledger_seed"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
style="@style/MoneroLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textColor="@color/colorAccent"
android:labelFor="@+id/etSeed"
android:text="@string/prompt_ledger_seed_warn" />
<android.support.design.widget.TextInputLayout
android:id="@+id/etSeed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
style="@style/MoneroEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_ledger_seed"
android:imeOptions="normal"
android:inputType="textMultiLine|textVisiblePassword" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/etPassphrase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
style="@style/MoneroEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_ledger_phrase"
android:imeOptions="normal"
android:inputType="textVisiblePassword" />
</android.support.design.widget.TextInputLayout>
<TextView
android:id="@+id/tvOpenPrompt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:visibility="gone" />
</LinearLayout>

View File

@@ -7,6 +7,13 @@
android:icon="@drawable/ic_help_white_24dp"
android:orderInCategory="100"
android:title="@string/menu_help"
app:showAsAction="always" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_ledger_seed"
android:icon="@drawable/ic_ledger_restore"
android:orderInCategory="200"
android:title="@string/menu_ledger_seed"
app:showAsAction="never" />
</menu>

View File

@@ -376,4 +376,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -375,4 +375,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -375,4 +375,10 @@
<string name="xmrto_error_012">Tro da mendoj</string>
<string name="street_sweep_amount">ĈIO!</string>
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -365,4 +365,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -373,4 +373,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -153,14 +153,14 @@
<p>Cest ladresse publique du portefeuille auquel vous allez envoyer des Moneroj, vous pouvez
la copier/coller, scanner un QR code ou la saisir manuellement. Vérifiez là bien trois fois
afin de vous assurer que vous nenvoyez pas de pièces à la mauvaise adresse.</p>
<p>In addition to using an XMR address, you can also use
<p>En complément de lutilisation d'une adresse XMR, vous pouvez aussi utiliser
<ul>
<li>an OpenAlias for XMR or BTC</li>
<li>a BTC address</li>
<li>a bitcoin: URI (including BIP70 like bitpay)</li>
<li>une adresse OpenAlias pour XMR ou BTC</li>
<li>une adresse BTC</li>
<li>une URI bitcoin: (incluant BIP70 comme bitpay)</li>
</u>
Please note, that sending BTC is processed through the XMR.TO service (see https://xmr.to
for details). See the section on sending BTC below.</p>
Notez que lenvoi de BTC est traité à travers le service XMR.TO (voir https://xmr.to pour
plus de détails). Voir la rubrique sur lenvoi de BTC plus bas.</p>
<h2>ID de Paiement</h2>
<p>Vous pouvez utiliser un ID de paiement pour identifier la raison pour laquelle vous avez
envoyé des Moneroj entre deux parties. Cest totallement privé et optionnel. Il permet par
@@ -313,14 +313,14 @@
<!-- Note for translators: new/changed text also in help_send -->
<string name="help_uri"><![CDATA[
<h1>Using a payment link</h1>
<p>You have started monerujo with a payment link. In order to send funds, please do the following:</p>
<h1>Utiliser un lien de paiement</h1>
<p>Vous avez démarré monerujo avec un lien de paiement. Afin denvoyer des fonds, merci de procéder comme suit :</p>
<p>
1. Open the wallet you want to spend from<br>
2. Wait until the wallet is synced &amp; the "Give" button appears<br>
3. Touch the "Give" button
1. Ouvrez le portefeuille à partir duquel vous souhaitez envoyer des fonds<br>
2. Attendez que le portefeuille soit synchronisé &amp; que le bouton "Envoyer" apparaisse<br>
3. Taper sur le bouton "Envoyer"
</p>
<p>The payment details will be filled in. Check them and proceed like for any other transaction.</p>
<p>Les détails du paiement seront remplis. Vérifiez-les et procédez de la même manière que pour toute autre transaction.</p>
]]></string>
<string name="help_ok">Got it!</string> <!-- Note: "Got it" as in "I understand this" -->

View File

@@ -367,16 +367,22 @@
<string name="node_nobookmark">%1$d meilleurs nœuds mis en favoris automatiquement</string>
<string name="label_test">Tester</string><!--note: as in "Test a network connection"-->
<string name="send_address_resolve_bip70">Resolving Payment URI&#8230;</string>
<string name="send_address_not_bip70">Could not resolve Payment URI</string>
<string name="send_address_bip70">Resolved Payment URI &#x2714;</string>
<string name="send_address_resolve_bip70">Résolution de l\'URI de Paiement&#8230;</string>
<string name="send_address_not_bip70">Résolution de l\'URI de Paiement impossible</string>
<string name="send_address_bip70">URI de Paiement Résolue &#x2714;</string>
<!-- please verify this means "Receiver" or "Recipient" as in "Receiver in the transaction" -->
<string name="send_address_hint">Destinataire</string>
<string name="xmrto_error_001">XMR.TO offline - try again later</string>
<string name="xmrto_error_004">BTC amount out of bounds</string>
<string name="xmrto_error_010">Invalid or outdated Payment URL</string>
<string name="xmrto_error_012">Too many requests</string>
<string name="xmrto_error_001">XMR.TO hors ligne - réessayer ultérieurement</string>
<string name="xmrto_error_004">Montant BTC hors limites</string>
<string name="xmrto_error_010">URL de Paiement invalide ou périmée</string>
<string name="xmrto_error_012">Trop de requêtes</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="street_sweep_amount">TOTALITÉ!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convertir mnémonique Ledger</string>
<string name="prompt_ledger_seed">Phrase mnémonique Ledger</string>
<string name="prompt_ledger_phrase">Mot de passe Ledger (optionnel)</string>
<string name="bad_ledger_seed">Phrase mnémonique Ledger invalide !</string>
<string name="prompt_ledger_seed_warn">Saisir votre phrase mnémonique Ledger ici est un risque majeur de sécurité !</string>
</resources>

View File

@@ -377,4 +377,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -378,4 +378,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -421,4 +421,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -375,4 +375,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -375,4 +375,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -367,4 +367,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -379,4 +379,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -375,4 +375,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

View File

@@ -379,4 +379,10 @@
<string name="xmrto_error_012">Too many requests</string>
<string name="street_sweep_amount">EVERYTHING!</string> <!-- as in: "everything in the account" = "all the money" -->
<string name="menu_ledger_seed">Convert Ledger Seed</string>
<string name="prompt_ledger_seed">Ledger Seed Words</string>
<string name="prompt_ledger_phrase">Ledger Passphrase (optional)</string>
<string name="bad_ledger_seed">Invalid Ledger Seed!</string>
<string name="prompt_ledger_seed_warn">Entering you Ledger Seed here is a major security risk!</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More