org.spongycastle.jce.interfaces.ECPublicKey Java Examples

The following examples show how to use org.spongycastle.jce.interfaces.ECPublicKey. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FixedCertFidoAttestationSigner.java    From UAF with Apache License 2.0 6 votes vote down vote up
public byte[] signWithAttestationCert(byte[] dataForSigning) {
    try {
        PrivateKey priv =
                KeyCodec.getPrivKey(Base64url.decode(AttestCert.priv));

        Log.i(TAG, " : dataForSigning : "
                + Base64url.encodeToString(dataForSigning));

        BigInteger[] signatureGen = NamedCurve.signAndFromatToRS(priv,
                SHA.sha(dataForSigning, "SHA-256"));

        boolean verify = NamedCurve.verify(
                KeyCodec.getBCKeyAsRawBytes((ECPublicKey) KeyCodec.getPubKey(Base64url.decode(AttestCert.pubCert))),
                SHA.sha(dataForSigning, "SHA-256"),
                Asn1.decodeToBigIntegerArray(Asn1.getEncoded(signatureGen)));
        if (!verify) {
            throw new RuntimeException("Signatire match fail");
        }
        byte[] ret = Asn1.toRawSignatureBytes(signatureGen);
        Log.i(TAG, " : signature : " + Base64url.encodeToString(ret));

        return ret;
    } catch(GeneralSecurityException | IOException e) {
        throw new RuntimeException(e);
    }
}
 
Example #2
Source File: KeyConverter.java    From bitseal with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Takes an encryption key derived from the double hash of a Bitmessage address
 * and uses it to create a public encryption key
 * 
 * @param encryptionKey - A byte[] containing the encryption key
 * 
 * @return An ECPublicKey object containing the new public key
 */
public ECPublicKey calculatePublicKeyFromDoubleHashKey (byte[] encryptionKey)
{
	// First calculate the private key, using the 'encryption key' derived from the double
	// hash of the address data, and extract its 'D' value. 
	ECPrivateKey privKey = reconstructPrivateKey(encryptionKey);
	BigInteger privKeyDValue = privKey.getD();
			
	// Use the 'D' value from the private key to create a new ECKeyPair object
	ECKeyPair keyPair = new ECKeyPair(privKeyDValue);
	
	// Takes the public key from the new key pair. 
	byte[] publicKeyBytes = keyPair.getPubKey();
	
	// Convert the public key bytes into a new ECPublicKey object
	ECPublicKey publicKey = reconstructPublicKey(publicKeyBytes);
	
	return publicKey;
}
 
Example #3
Source File: ProvisioningPublicKeyState.java    From Android-nRF-Mesh-Library with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
private void generateKeyPairs() {

        try {
            final ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
            final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "SC");
            keyPairGenerator.initialize(parameterSpec);
            final KeyPair keyPair = keyPairGenerator.generateKeyPair();
            final ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();

            mProvisionerPrivaetKey = (ECPrivateKey) keyPair.getPrivate();

            final ECPoint point = publicKey.getQ();

            final BigInteger x = point.getXCoord().toBigInteger();
            final BigInteger y = point.getYCoord().toBigInteger();
            final byte[] tempX = BigIntegers.asUnsignedByteArray(32, x);
            final byte[] tempY = BigIntegers.asUnsignedByteArray(32, y);

            Log.v(TAG, "X: length: " + tempX.length + " " + MeshParserUtils.bytesToHex(tempX, false));
            Log.v(TAG, "Y: length: " + tempY.length + " " + MeshParserUtils.bytesToHex(tempY, false));

            final byte[] tempXY = new byte[64];
            System.arraycopy(tempX, 0, tempXY, 0, tempX.length);
            System.arraycopy(tempY, 0, tempXY, tempY.length, tempY.length);

            mUnprovisionedMeshNode.setProvisionerPublicKeyXY(tempXY);

            Log.v(TAG, "XY: " + MeshParserUtils.bytesToHex(tempXY, true));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
Example #4
Source File: CryptProcessor.java    From bitseal with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Encrypts the given data using the supplied public key.<br><br>
 * 
 * See https://bitmessage.org/wiki/Encryption and https://bitmessage.org/forum/index.php?topic=2848.0
 * 
 * @param plain - A byte[] containing the data to be encrypted.
 * @param K - An ECPublicKey object containing the public key 'K' to encrypt the data with.
 * 
 * @return A byte[] containing the encrypted payload.
 */
public byte[] encrypt (byte[] plain, ECPublicKey K)
{
	KeyPair random = generateEncryptionKeyPair();
	ECPublicKey R = (ECPublicKey) random.getPublic();
	BigInteger r = ((ECPrivateKey)random.getPrivate()).getD();
	
	ECPoint P = K.getQ().multiply(r);

	byte[] tmpKey = deriveKey(P);
	byte[] key_e = ArrayCopier.copyOfRange(tmpKey, 0, 32);
	byte[] key_m = ArrayCopier.copyOfRange(tmpKey, 32, 64);

	byte[] iv = new byte[16];
	new SecureRandom().nextBytes(iv);

	byte[] cipherText = doAES(key_e, iv, plain, true);
	
	byte[] x = ByteUtils.getUnsignedBytes(R.getQ().getX().toBigInteger(), 32);
	byte[] y = ByteUtils.getUnsignedBytes(R.getQ().getY().toBigInteger(), 32);

	int xLength = x.length;
	int yLength = y.length;
	
	byte[] encodedR = ByteUtils.concatenateByteArrays(ByteUtils.shortToBytes((short) 714), ByteUtils.shortToBytes((short) xLength), x, ByteUtils.shortToBytes((short) yLength), y);
	
	byte[] dataForMac = ByteUtils.concatenateByteArrays(iv, encodedR, cipherText);
	byte[] mac = SHA256.hmacSHA256(dataForMac, key_m);

	byte[] encryptedPayload = ByteUtils.concatenateByteArrays(iv, encodedR, cipherText, mac);
	
	return encryptedPayload;
}
 
Example #5
Source File: CryptProcessor.java    From bitseal with GNU General Public License v3.0 5 votes vote down vote up
/** 
 * Decrypts an encrypted msg.<br><br>
 * 
 * <b>NOTE! If decryption fails, this method will throw a RuntimeException</b>
 *  
 * @param encryptedPayload - A byte[] containing the data to be decrypted
 * @param k - The ECPrivateKey object used to decrypt the data
 * 
 * @return A byte[] containing the decrypted plain text
 */
public byte[] decrypt (byte[] encryptedPayload, ECPrivateKey k)
{
	// Parse the data from the encrypted payload
	EncryptedPayload encPay = parseEncryptedPayload(encryptedPayload);
	byte[] iv = encPay.getIV();
	BigInteger x = encPay.getX();
	BigInteger y = encPay.getY();
	byte[] cipherText = encPay.getCipherText();
	byte[] mac = encPay.getMac();
	
	// Reconstruct public key R
	ECPublicKey R = createPublicEncryptionKey(x, y);

	// Now that we have parsed all the data from the encrypted payload, we can begin the decryption process.
	// First, do an EC point multiply with private key k and public key R. This gives you public key P. 
	ECPoint P = R.getQ().multiply(k.getD());

	byte[] tmpKey = deriveKey(P);
	byte[] key_e = ArrayCopier.copyOf(tmpKey, 32);
	byte[] key_m = ArrayCopier.copyOfRange(tmpKey, 32, 64);

	// Check whether the mac is valid	
	byte[] dataForMac = ArrayCopier.copyOfRange(encryptedPayload, 0, encryptedPayload.length - 32); // The mac now covers everything except itself
	byte[] expectedMAC = SHA256.hmacSHA256(dataForMac, key_m);
	
	if (Arrays.equals(mac, expectedMAC) == false)
	{
		// The mac is invalid
		throw new RuntimeException("While attempting to decrypt an encrypted payload in CryptProcessor.decryptMsg(), the mac was found to be invalid");
	}
	else
	{
		// The mac is valid. Decrypt the parsed data
		return doAES(key_e, iv, cipherText, false);
	}
}
 
Example #6
Source File: PubkeyProcessor.java    From bitseal with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Checks whether a given Pubkey and Bitmessage address are valid for
 * each other. 
 * 
 * @param pubkey - A Pubkey object to be validated
 * @param addressString - A String containing the Bitmessage address to 
 * validate the Pubkey against
 * 
 * @return A boolean indicating whether or not the Pubkey and address String
 * are valid for each other
 */
public boolean validatePubkey (Pubkey pubkey, String addressString)
{
	// First check that the given address string is a valid Bitmessage address.
	AddressProcessor addProc = new AddressProcessor();
	boolean addressStringValid = addProc.validateAddress(addressString);
	if (addressStringValid == false)
	{
		Log.i(TAG, "While running PubkeyProcessor.validatePubkey(), it was found that the supplied \n" +
				"address String was NOT a valid Bitmessage address");
		return false;
	}
	
	// Check that the pubkey is valid by using its public signing key, public encryption key, 
	// address version number, and stream number to recreate the address string that it corresponds to.
	// This should match the address string that we started with.
	AddressGenerator addGen = new AddressGenerator();
	String recreatedAddress = addGen.recreateAddressString(pubkey.getObjectVersion(), pubkey.getStreamNumber(),
			pubkey.getPublicSigningKey(), pubkey.getPublicEncryptionKey());
	
	Log.i(TAG, "Recreated address String: " + recreatedAddress);
	boolean recreatedAddressValid = recreatedAddress.equals(addressString);
	if (recreatedAddressValid == false)
	{
		Log.i(TAG, "While running PubkeyProcessor.validatePubkey(), it was found that the recreated address String \n" +
				    "generated using data from the pubkey did not match the original address String. \n" +
					"The original address String was : " + addressString + "\n" +
					"The recreated address String was: " + recreatedAddress);
		return false;
	}
	
	// If this pubkey is of version 2 or above, also check that the signature of the pubkey is valid
	int[] addressNumbers = addProc.decodeAddressNumbers(addressString);
	int addressVersion = addressNumbers[0];
	if (addressVersion > 2)
	{
		// To verify the signature we first have to convert the public signing key from the retrieved pubkey into an ECPublicKey object
		KeyConverter keyConv = new KeyConverter();
		ECPublicKey publicSigningKey = keyConv.reconstructPublicKey(pubkey.getPublicSigningKey());
		
		SigProcessor sigProc = new SigProcessor();
		byte[] signaturePayload = sigProc.createPubkeySignaturePayload(pubkey);
		boolean sigValid = (sigProc.verifySignature(signaturePayload, pubkey.getSignature(), publicSigningKey));
		
		if (sigValid == false)
		{
			Log.i(TAG, "While running PubkeyProcessor.validatePubkey(), it was found that the pubkey's signature was invalid");
			return false;
		}
	}
	
	// If the recreated address String and signature were both valid
	return true;
}
 
Example #7
Source File: PubkeyProcessor.java    From bitseal with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Takes a Pubkey and encodes it into a single byte[] (in a way that is compatible
 * with the way that PyBitmessage does), and does POW for this payload. This payload
 * can then be sent to a server to be disseminated across the network. <br><br>
 * 
 * Note: This method is currently only valid for version 4 pubkeys
 * 
 * @param pubkey - An Pubkey object containing the pubkey data used to create
 * the payload.
 * @param doPOW - A boolean value indicating whether or not to do POW for this pubkey
 * 
 * @return A Payload object containing the pubkey payload
 */
public Payload constructPubkeyPayload (Pubkey pubkey, boolean doPOW)
{
	// Construct the pubkey payload
	byte[] payload = null;
	ByteArrayOutputStream payloadStream = new ByteArrayOutputStream();
	try
	{
		payloadStream.write(ByteUtils.longToBytes(pubkey.getExpirationTime()));
		payloadStream.write(ByteUtils.intToBytes(pubkey.getObjectType()));
		payloadStream.write(VarintEncoder.encode(pubkey.getObjectVersion())); 
		payloadStream.write(VarintEncoder.encode(pubkey.getStreamNumber())); 
		
		// Assemble the pubkey data that will be encrypted
		ByteArrayOutputStream dataToEncryptStream = new ByteArrayOutputStream();
		
		dataToEncryptStream.write(ByteUtils.intToBytes(pubkey.getBehaviourBitfield()));
		
		// If the public signing and public encryption keys have their leading 0x04 byte in place then we need to remove them
		byte[] publicSigningKey = pubkey.getPublicSigningKey();
		if (publicSigningKey[0] == (byte) 4  && publicSigningKey.length == 65)
		{
			publicSigningKey = ArrayCopier.copyOfRange(publicSigningKey, 1, publicSigningKey.length);
		}
		dataToEncryptStream.write(publicSigningKey);
		
		byte[] publicEncryptionKey = pubkey.getPublicEncryptionKey();
		if (publicEncryptionKey[0] == (byte) 4  && publicEncryptionKey.length == 65)
		{
			publicEncryptionKey = ArrayCopier.copyOfRange(publicEncryptionKey, 1, publicEncryptionKey.length);
		}
		dataToEncryptStream.write(publicEncryptionKey);
		
		dataToEncryptStream.write(VarintEncoder.encode(pubkey.getNonceTrialsPerByte()));
		dataToEncryptStream.write(VarintEncoder.encode(pubkey.getExtraBytes()));
		dataToEncryptStream.write(VarintEncoder.encode(pubkey.getSignatureLength()));
		dataToEncryptStream.write(pubkey.getSignature());
		
		// Create the ECPublicKey object that we will use to encrypt the data. First we will
		// retrieve the Address corresponding to this pubkey, so that we can calculate the encryption
		// key derived from the double hash of the address data.
		Address address = AddressProvider.get(App.getContext()).searchForSingleRecord(pubkey.getCorrespondingAddressId());
		String addressString = address.getAddress();
		byte[] encryptionKey = new AddressProcessor().calculateAddressEncryptionKey(addressString);
		ECPublicKey K = new KeyConverter().calculatePublicKeyFromDoubleHashKey(encryptionKey);
		
		// Encrypt the pubkey data
		byte[] dataToEncrypt = dataToEncryptStream.toByteArray();
		byte[] encryptedPayload = new CryptProcessor().encrypt(dataToEncrypt, K);
		
		// Get the tag used to identify the pubkey payload
		byte[] tag = address.getTag();
		
		// Add the tag and the encrypted data to the rest of the pubkey payload
		payloadStream.write(tag);
		payloadStream.write(encryptedPayload);

		payload = payloadStream.toByteArray();
	} 
	catch (IOException e)
	{
		throw new RuntimeException("IOException occurred in PubkeyProcessor.constructPubkeyPayloadForDissemination()", e);
	}
		
	if (doPOW)
	{
		long powNonce = new POWProcessor().doPOW(payload, pubkey.getExpirationTime(), POWProcessor.NETWORK_NONCE_TRIALS_PER_BYTE, POWProcessor.NETWORK_EXTRA_BYTES);
		payload = ByteUtils.concatenateByteArrays(ByteUtils.longToBytes(powNonce), payload);
	}
	
	// Create a new Payload object to hold the payload data
	Payload pubkeyPayload = new Payload();
	pubkeyPayload.setRelatedAddressId(pubkey.getCorrespondingAddressId());
	pubkeyPayload.setBelongsToMe(true);
	pubkeyPayload.setPOWDone(doPOW);
	pubkeyPayload.setType(Payload.OBJECT_TYPE_PUBKEY);
	pubkeyPayload.setPayload(payload);
	
	// Save the Payload object to the database
	PayloadProvider payProv = PayloadProvider.get(App.getContext());
	long pubkeyPayloadID = payProv.addPayload(pubkeyPayload);
	
	// Finally, set the pubkey payload's ID to the one generated by the database
	pubkeyPayload.setId(pubkeyPayloadID);
	
	return pubkeyPayload;
}
 
Example #8
Source File: OutgoingMessageProcessor.java    From bitseal with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Takes an UnencryptedMsg object and does all the work necessary to transform it into an EncyrptedMsg
 * object that is ready to be serialised and sent out to the Bitmessage network. The two major parts of this
 * process are encryption and proof of work. <br><br>
 * 
 * <b>NOTE!</b> Calling this method results in proof of work calculations being done for the
 * message. This can take a long time and lots of CPU power!<br><br>
 * 
 * @param message - The original plain text Message object, provided so that its status can be updated during the process
 * @param unencMsg - The UnencryptedMsg object to be encrypted
 * @param toPubkey - The Pubkey object containing the public encryption key of the intended message recipient
 * @param doPOW - A boolean value indicating whether or not POW should be done for this message
 * @param timeToLive - The 'time to live' value (in seconds) to be used in creating this msg
 * 
 * @return A Msg object containing the encrypted message data
 */
private BMObject constructMsg (Message message, UnencryptedMsg unencMsg, Pubkey toPubkey, boolean doPOW, long timeToLive)
{		
	// Reconstruct the ECPublicKey object from the byte[] found the the relevant PubKey
	ECPublicKey publicEncryptionKey = new KeyConverter().reconstructPublicKey(toPubkey.getPublicEncryptionKey());
	
	// Construct the payload to be encrypted
	byte[] msgDataForEncryption = constructMsgPayloadForEncryption(unencMsg);
			
	// Update the status of this message displayed in the UI
	String messageStatus = App.getContext().getString(R.string.message_status_encrypting_message);
	MessageStatusHandler.updateMessageStatus(message, messageStatus);
	
	// Encrypt the payload
	CryptProcessor cryptProc = new CryptProcessor();
	byte[] encryptedPayload = cryptProc.encrypt(msgDataForEncryption, publicEncryptionKey);
			
	// Create a new Msg object and populate its fields
	BMObject msg = new BMObject();
	msg.setBelongsToMe(true); // NOTE: This method assumes that any message I am encrypting 'belongs to me' (i.e. The user of the application is the author of the message)
	msg.setExpirationTime(unencMsg.getExpirationTime());
	msg.setObjectType(unencMsg.getObjectType());
	msg.setObjectVersion(unencMsg.getObjectVersion());
	msg.setStreamNumber(toPubkey.getStreamNumber());
	msg.setPayload(encryptedPayload);
	
	if (doPOW)
	{
		MessageStatusHandler.updateMessageStatus(message, App.getContext().getString(R.string.message_status_doing_pow));
		
		// Do proof of work for the Msg object
		Log.i(TAG, "About to do POW calculations for a msg that we are sending");
		byte[] powPayload = constructMsgPayloadForPOW(msg);
		long powNonce = new POWProcessor().doPOW(powPayload, unencMsg.getExpirationTime(), toPubkey.getNonceTrialsPerByte(), toPubkey.getExtraBytes());
		msg.setPOWNonce(powNonce);
	}
	else
	{
		msg.setPOWNonce((long) 0); // If POW is not to be done for this message, set the powNonce as zero for now.
	}
	
	return msg;
}