All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.crypto.tink.subtle.X25519 Maven / Gradle / Ivy

Go to download

Tink is a small cryptographic library that provides a safe, simple, agile and fast way to accomplish some common cryptographic tasks.

There is a newer version: 1.16.0
Show newest version
// Copyright 2017 Google Inc.
//
// 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.google.crypto.tink.subtle;

import com.google.crypto.tink.annotations.Alpha;
import java.security.InvalidKeyException;
import java.util.Arrays;

/**
 * Defines the ECDH Curve25519 function,
 * also known as the X25519 function.
 *
 * 

This implementation is based on curve255-donna. * *

Warning

* *

Do not use this API or any other APIs including fields and methods marked with the @Alpha * annotation. They can be modified in any way, or even removed, at any time. They are in the * package, but not for official, production release, but only for testing. * *

Usage

* *
 * Alice:
 * byte[] privateKeyA = X25519.generatePrivateKey();
 * byte[] publicKeyA = X25519.publicFromPrivate(privateKeyA);
 * Bob:
 * byte[] privateKeyB = X25519.generatePrivateKey();
 * byte[] publicKeyB = X25519.publicFromPrivate(privateKeyB);
 *
 * Alice sends publicKeyA to Bob and Bob sends publicKeyB to Alice.
 * Alice:
 * byte[] sharedSecretA = X25519.computeSharedSecret(privateKeyA, publicKeyB);
 * Bob:
 * byte[] sharedSecretB = X25519.computeSharedSecret(privateKeyB, publicKeyA);
 * such that sharedSecretA == sharedSecretB.
 * 
*/ @Alpha public final class X25519 { /** * Returns a 32-byte private key for Curve25519. * *

Note from BoringSSL: All X25519 implementations should decode scalars correctly (see * https://tools.ietf.org/html/rfc7748#section-5). However, if an implementation doesn't then it * might interoperate with random keys a fraction of the time because they'll, randomly, happen to * be correctly formed. * *

Thus we do the opposite of the masking here to make sure that our private keys are never * correctly masked and so, hopefully, any incorrect implementations are deterministically broken. * *

This does not affect security because, although we're throwing away entropy, a valid * implementation of computeSharedSecret should throw away the exact same bits anyway. */ @SuppressWarnings("NarrowingCompoundAssignment") public static byte[] generatePrivateKey() { byte[] privateKey = Random.randBytes(Field25519.FIELD_LEN); privateKey[0] |= 7; privateKey[31] &= 63; privateKey[31] |= 128; return privateKey; } /** * Returns the 32-byte shared key (i.e., privateKey·peersPublicValue on the curve). * * @param privateKey 32-byte private key * @param peersPublicValue 32-byte public value * @return the 32-byte shared key * @throws InvalidKeyException when {@code privateKey} is not 32-byte or {@code peersPublicValue} * is invalid. */ @SuppressWarnings("NarrowingCompoundAssignment") public static byte[] computeSharedSecret(byte[] privateKey, byte[] peersPublicValue) throws InvalidKeyException { if (privateKey.length != Field25519.FIELD_LEN) { throw new InvalidKeyException("Private key must have 32 bytes."); } long[] x = new long[Field25519.LIMB_CNT + 1]; byte[] e = Arrays.copyOf(privateKey, Field25519.FIELD_LEN); e[0] &= 248; e[31] &= 127; e[31] |= 64; Curve25519.curveMult(x, e, peersPublicValue); return Field25519.contract(x); } /** * Returns the 32-byte Diffie-Hellman public value based on the given {@code privateKey} (i.e., * {@code privateKey}·[9] on the curve). * * @param privateKey 32-byte private key * @return 32-byte Diffie-Hellman public value * @throws InvalidKeyException when the {@code privateKey} is not 32 bytes. */ public static byte[] publicFromPrivate(byte[] privateKey) throws InvalidKeyException { if (privateKey.length != Field25519.FIELD_LEN) { throw new InvalidKeyException("Private key must have 32 bytes."); } byte[] base = new byte[Field25519.FIELD_LEN]; base[0] = 9; return computeSharedSecret(privateKey, base); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy