KeyEncoding: Clean up and reorganize to match style
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
		
							parent
							
								
									c3afe5be2c
								
							
						
					
					
						commit
						f0f9192aed
					
				@ -91,7 +91,7 @@ public class Interface extends BaseObservable implements Observable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public void setPrivateKey(String privateKey) {
 | 
					    public void setPrivateKey(String privateKey) {
 | 
				
			||||||
        // Avoid exceptions from Keypair while the user is typing.
 | 
					        // Avoid exceptions from Keypair while the user is typing.
 | 
				
			||||||
        if (privateKey.length() != KeyEncoding.WG_KEY_LEN_BASE64)
 | 
					        if (privateKey.length() != KeyEncoding.KEY_LENGTH_BASE64)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        keypair = new Keypair(privateKey);
 | 
					        keypair = new Keypair(privateKey);
 | 
				
			||||||
        notifyPropertyChanged(BR.privateKey);
 | 
					        notifyPropertyChanged(BR.privateKey);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,75 +1,91 @@
 | 
				
			|||||||
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
 | 
					/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This is a specialized constant-time base64 implementation that resists side-channel attacks.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package com.wireguard.crypto;
 | 
					package com.wireguard.crypto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This is a specialized constant-time base64 implementation that resists side-channel attacks.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class KeyEncoding {
 | 
					public class KeyEncoding {
 | 
				
			||||||
	public static final int WG_KEY_LEN = 32;
 | 
					    public static final int KEY_LENGTH = 32;
 | 
				
			||||||
	public static final int WG_KEY_LEN_BASE64 = 44;
 | 
					    public static final int KEY_LENGTH_BASE64 = 44;
 | 
				
			||||||
 | 
					    private static final String KEY_LENGTH_BASE64_EXCEPTION_MESSAGE =
 | 
				
			||||||
 | 
					            "WireGuard base64 keys must be 44 characters encoding 32 bytes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static void encodeBase64(char dest[], final int dest_offset, final byte src[], final int src_offset) {
 | 
					    private static int decodeBase64(final char[] src, final int src_offset) {
 | 
				
			||||||
		final byte input[] = { (byte)((src[0 + src_offset] >>> 2) & 63),
 | 
					        int val = 0;
 | 
				
			||||||
				       (byte)(((src[0 + src_offset] << 4) | ((src[1 + src_offset] & 0xff) >>> 4)) & 63),
 | 
					        for (int i = 0; i < 4; ++i) {
 | 
				
			||||||
				       (byte)(((src[1 + src_offset] << 2) | ((src[2 + src_offset] & 0xff) >>> 6)) & 63),
 | 
					            final char c = src[i + src_offset];
 | 
				
			||||||
				       (byte)(src[2 + src_offset] & 63) };
 | 
					            val |= (-1
 | 
				
			||||||
		for (int i = 0; i < 4; ++i)
 | 
					                    + ((((('A' - 1) - c) & (c - ('Z' + 1))) >>> 8) & (c - 64))
 | 
				
			||||||
			dest[i + dest_offset] = (char)(input[i] + 'A'
 | 
					                    + ((((('a' - 1) - c) & (c - ('z' + 1))) >>> 8) & (c - 70))
 | 
				
			||||||
						+ (((25 - input[i]) >>> 8) & 6)
 | 
					                    + ((((('0' - 1) - c) & (c - ('9' + 1))) >>> 8) & (c + 5))
 | 
				
			||||||
						- (((51 - input[i]) >>> 8) & 75)
 | 
					                    + ((((('+' - 1) - c) & (c - ('+' + 1))) >>> 8) & 63)
 | 
				
			||||||
						- (((61 - input[i]) >>> 8) & 15)
 | 
					                    + ((((('/' - 1) - c) & (c - ('/' + 1))) >>> 8) & 64)
 | 
				
			||||||
						+ (((62 - input[i]) >>> 8) & 3));
 | 
					            ) << (18 - 6 * i);
 | 
				
			||||||
	}
 | 
					        }
 | 
				
			||||||
 | 
					        return val;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static String keyToBase64(final byte key[]) {
 | 
					    private static void encodeBase64(final byte[] src, final int src_offset,
 | 
				
			||||||
		if (key.length != WG_KEY_LEN)
 | 
					                                     char[] dest, final int dest_offset) {
 | 
				
			||||||
			throw new IllegalArgumentException("WireGuard keys must be 32 bytes");
 | 
					        final byte[] input = {
 | 
				
			||||||
		final char base64[] = new char[WG_KEY_LEN_BASE64];
 | 
					                (byte) ((src[0 + src_offset] >>> 2) & 63),
 | 
				
			||||||
		int i;
 | 
					                (byte) ((src[0 + src_offset] << 4 | ((src[1 + src_offset] & 0xff) >>> 4)) & 63),
 | 
				
			||||||
		for (i = 0; i < WG_KEY_LEN / 3; ++i)
 | 
					                (byte) ((src[1 + src_offset] << 2 | ((src[2 + src_offset] & 0xff) >>> 6)) & 63),
 | 
				
			||||||
			encodeBase64(base64, i * 4, key, i * 3);
 | 
					                (byte) ((src[2 + src_offset]) & 63),
 | 
				
			||||||
		final byte endSegment[] = { key[i * 3 + 0], key[i * 3 + 1], 0 };
 | 
					        };
 | 
				
			||||||
		encodeBase64(base64, i * 4, endSegment, 0);
 | 
					        for (int i = 0; i < 4; ++i) {
 | 
				
			||||||
		base64[WG_KEY_LEN_BASE64 - 1] = '=';
 | 
					            dest[i + dest_offset] = (char) (input[i] + 'A'
 | 
				
			||||||
		return new String(base64);
 | 
					                    + (((25 - input[i]) >>> 8) & 6)
 | 
				
			||||||
	}
 | 
					                    - (((51 - input[i]) >>> 8) & 75)
 | 
				
			||||||
 | 
					                    - (((61 - input[i]) >>> 8) & 15)
 | 
				
			||||||
 | 
					                    + (((62 - input[i]) >>> 8) & 3));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static int decodeBase64(final char src[], int src_offset) {
 | 
					    public static byte[] keyFromBase64(final String str) {
 | 
				
			||||||
		int val = 0;
 | 
					        final char[] input = str.toCharArray();
 | 
				
			||||||
		for (int i = 0; i < 4; ++i)
 | 
					        final byte[] key = new byte[KEY_LENGTH];
 | 
				
			||||||
			val |= (-1
 | 
					        if (input.length != KEY_LENGTH_BASE64 || input[KEY_LENGTH_BASE64 - 1] != '=')
 | 
				
			||||||
				    + ((((('A' - 1) - src[i + src_offset]) & (src[i + src_offset] - ('Z' + 1))) >>> 8) & (src[i + src_offset] - 64))
 | 
					            throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
 | 
				
			||||||
				    + ((((('a' - 1) - src[i + src_offset]) & (src[i + src_offset] - ('z' + 1))) >>> 8) & (src[i + src_offset] - 70))
 | 
					        int i;
 | 
				
			||||||
				    + ((((('0' - 1) - src[i + src_offset]) & (src[i + src_offset] - ('9' + 1))) >>> 8) & (src[i + src_offset] + 5))
 | 
					        for (i = 0; i < KEY_LENGTH / 3; ++i) {
 | 
				
			||||||
				    + ((((('+' - 1) - src[i + src_offset]) & (src[i + src_offset] - ('+' + 1))) >>> 8) & 63)
 | 
					            final int val = decodeBase64(input, i * 4);
 | 
				
			||||||
				    + ((((('/' - 1) - src[i + src_offset]) & (src[i + src_offset] - ('/' + 1))) >>> 8) & 64)
 | 
					            if (val < 0)
 | 
				
			||||||
				) << (18 - 6 * i);
 | 
					                throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
 | 
				
			||||||
		return val;
 | 
					            key[i * 3 + 0] = (byte) ((val >>> 16) & 0xff);
 | 
				
			||||||
	}
 | 
					            key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff);
 | 
				
			||||||
 | 
					            key[i * 3 + 2] = (byte) (val & 0xff);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        final char[] endSegment = {
 | 
				
			||||||
 | 
					                input[i * 4 + 0],
 | 
				
			||||||
 | 
					                input[i * 4 + 1],
 | 
				
			||||||
 | 
					                input[i * 4 + 2],
 | 
				
			||||||
 | 
					                'A',
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        final int val = decodeBase64(endSegment, 0);
 | 
				
			||||||
 | 
					        if (val < 0 || (val & 0xff) != 0)
 | 
				
			||||||
 | 
					            throw new IllegalArgumentException(KEY_LENGTH_BASE64_EXCEPTION_MESSAGE);
 | 
				
			||||||
 | 
					        key[i * 3 + 0] = (byte) ((val >>> 16) & 0xff);
 | 
				
			||||||
 | 
					        key[i * 3 + 1] = (byte) ((val >>> 8) & 0xff);
 | 
				
			||||||
 | 
					        return key;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static byte[] keyFromBase64(final String input) {
 | 
					    public static String keyToBase64(final byte[] key) {
 | 
				
			||||||
		final char base64[] = input.toCharArray();
 | 
					        final char[] output = new char[KEY_LENGTH_BASE64];
 | 
				
			||||||
		if (base64.length != WG_KEY_LEN_BASE64 || base64[WG_KEY_LEN_BASE64 - 1] != '=')
 | 
					        if (key.length != KEY_LENGTH)
 | 
				
			||||||
			throw new IllegalArgumentException("WireGuard base64 keys must be 44 characters encoding 32 bytes");
 | 
					            throw new IllegalArgumentException("WireGuard keys must be 32 bytes");
 | 
				
			||||||
		final byte key[] = new byte[WG_KEY_LEN];
 | 
					        int i;
 | 
				
			||||||
		int i;
 | 
					        for (i = 0; i < KEY_LENGTH / 3; ++i)
 | 
				
			||||||
		int val;
 | 
					            encodeBase64(key, i * 3, output, i * 4);
 | 
				
			||||||
 | 
					        final byte[] endSegment = {
 | 
				
			||||||
		for (i = 0; i < WG_KEY_LEN / 3; ++i) {
 | 
					                key[i * 3 + 0],
 | 
				
			||||||
			val = decodeBase64(base64, i * 4);
 | 
					                key[i * 3 + 1],
 | 
				
			||||||
			if (val < 0)
 | 
					                0,
 | 
				
			||||||
				throw new IllegalArgumentException("WireGuard base64 keys must be 44 characters encoding 32 bytes");
 | 
					        };
 | 
				
			||||||
			key[i * 3 + 0] = (byte)((val >>> 16) & 0xff);
 | 
					        encodeBase64(endSegment, 0, output, i * 4);
 | 
				
			||||||
			key[i * 3 + 1] = (byte)((val >>> 8) & 0xff);
 | 
					        output[KEY_LENGTH_BASE64 - 1] = '=';
 | 
				
			||||||
			key[i * 3 + 2] = (byte)(val & 0xff);
 | 
					        return new String(output);
 | 
				
			||||||
		}
 | 
					    }
 | 
				
			||||||
		final char endSegment[] = { base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A' };
 | 
					 | 
				
			||||||
		val = decodeBase64(endSegment, 0);
 | 
					 | 
				
			||||||
		if (val < 0 || (val & 0xff) != 0)
 | 
					 | 
				
			||||||
			throw new IllegalArgumentException("WireGuard base64 keys must be 44 characters encoding 32 bytes");
 | 
					 | 
				
			||||||
		key[i * 3 + 0] = (byte)((val >>> 16) & 0xff);
 | 
					 | 
				
			||||||
		key[i * 3 + 1] = (byte)((val >>> 8) & 0xff);
 | 
					 | 
				
			||||||
		return key;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,5 @@
 | 
				
			|||||||
package com.wireguard.crypto;
 | 
					package com.wireguard.crypto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.util.Base64;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.security.SecureRandom;
 | 
					import java.security.SecureRandom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -11,7 +9,7 @@ import java.security.SecureRandom;
 | 
				
			|||||||
public class Keypair {
 | 
					public class Keypair {
 | 
				
			||||||
    private static byte[] generatePrivateKey() {
 | 
					    private static byte[] generatePrivateKey() {
 | 
				
			||||||
        final SecureRandom secureRandom = new SecureRandom();
 | 
					        final SecureRandom secureRandom = new SecureRandom();
 | 
				
			||||||
        final byte[] privateKey = new byte[KeyEncoding.WG_KEY_LEN];
 | 
					        final byte[] privateKey = new byte[KeyEncoding.KEY_LENGTH];
 | 
				
			||||||
        secureRandom.nextBytes(privateKey);
 | 
					        secureRandom.nextBytes(privateKey);
 | 
				
			||||||
        privateKey[0] &= 248;
 | 
					        privateKey[0] &= 248;
 | 
				
			||||||
        privateKey[31] &= 127;
 | 
					        privateKey[31] &= 127;
 | 
				
			||||||
@ -20,7 +18,7 @@ public class Keypair {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static byte[] generatePublicKey(byte[] privateKey) {
 | 
					    private static byte[] generatePublicKey(byte[] privateKey) {
 | 
				
			||||||
        final byte[] publicKey = new byte[KeyEncoding.WG_KEY_LEN];
 | 
					        final byte[] publicKey = new byte[KeyEncoding.KEY_LENGTH];
 | 
				
			||||||
        Curve25519.eval(publicKey, 0, privateKey, null);
 | 
					        Curve25519.eval(publicKey, 0, privateKey, null);
 | 
				
			||||||
        return publicKey;
 | 
					        return publicKey;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user