List of usage examples for org.bouncycastle.crypto BasicAgreement init
void init(CipherParameters param);
From source file:COSE.Recipient.java
private byte[] ECDH_GenerateSecret(OneKey key) throws CoseException { OneKey epk;//from ww w .j a v a 2 s . c o m if (senderKey != null) { epk = key; key = senderKey; } else { CBORObject cn; cn = findAttribute(HeaderKeys.ECDH_SPK); if (cn == null) { cn = findAttribute(HeaderKeys.ECDH_EPK); } if (cn == null) throw new CoseException("No second party EC key"); epk = new OneKey(cn); } if (key.get(KeyKeys.KeyType.AsCBOR()) != KeyKeys.KeyType_EC2) throw new CoseException("Not an EC2 Key"); if (epk.get(KeyKeys.KeyType.AsCBOR()) != KeyKeys.KeyType_EC2) throw new CoseException("Not an EC2 Key"); if (epk.get(KeyKeys.EC2_Curve.AsCBOR()) != key.get(KeyKeys.EC2_Curve.AsCBOR())) throw new CoseException("Curves are not the same"); X9ECParameters p = epk.GetCurve(); ECDomainParameters parameters = new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH()); ECPoint pubPoint; CBORObject y = epk.get(KeyKeys.EC2_Y.AsCBOR()); byte[] x = epk.get(KeyKeys.EC2_X.AsCBOR()).GetByteString(); if (y.getType() == CBORType.Boolean) { byte[] X = epk.get(KeyKeys.EC2_X.AsCBOR()).GetByteString(); byte[] rgb = new byte[X.length + 1]; System.arraycopy(X, 0, rgb, 1, X.length); rgb[0] = (byte) (2 + (y.AsBoolean() ? 1 : 0)); pubPoint = p.getCurve().decodePoint(rgb); } else { pubPoint = p.getCurve().createPoint(new BigInteger(1, x), new BigInteger(1, y.GetByteString())); } ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters); ECPrivateKeyParameters priv = new ECPrivateKeyParameters( new BigInteger(1, key.get(KeyKeys.EC2_D.AsCBOR()).GetByteString()), parameters); BasicAgreement e1 = new ECDHBasicAgreement(); e1.init(priv); BigInteger k1 = e1.calculateAgreement(pub); return BigIntegers.asUnsignedByteArray((p.getCurve().getFieldSize() + 7) / 8, k1); }
From source file:dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerClient.java
License:Apache License
@SuppressWarnings("Duplicates") void readClient(final Channel channel, final Registration registration, final String type, final MetaChannel metaChannel) { final InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress(); // IN: session ID + public key + ecc parameters (which are a nonce. the SERVER defines what these are) // OUT: remote ECDH shared payload if (metaChannel.aesKey == null && registration.publicKey != null) { // whoa! Didn't send valid public key info! if (invalidPublicKey(registration, type)) { shutdown(channel, registration.sessionID); return; }//from w ww. jav a 2 s. com // want to validate the public key used! This is similar to how SSH works, in that once we use a public key, we want to validate // against that ip-address::key pair, so we can better protect against MITM/spoof attacks. if (invalidRemoteAddress(metaChannel, registration, type, remoteAddress)) { // whoa! abort since something messed up! (log and recording if key changed happens inside of validate method) shutdown(channel, registration.sessionID); return; } // save off remote public key. This is ALWAYS the same, where the ECDH changes every time... metaChannel.publicKey = registration.publicKey; // It is OK that we generate a new ECC keypair for ECDHE every time that we connect from the client. // The server rotates keys every XXXX seconds, since this step is expensive (and the server is the 'trusted' endpoint). metaChannel.ecdhKey = CryptoECC.generateKeyPair(eccSpec, registrationWrapper.getSecureRandom()); Registration outboundRegister = new Registration(metaChannel.sessionId); Output output = new Output(1024); EccPublicKeySerializer.write(output, (ECPublicKeyParameters) metaChannel.ecdhKey.getPublic()); outboundRegister.payload = output.toBytes(); channel.writeAndFlush(outboundRegister); return; } // IN: remote ECDH shared payload // OUT: hasMore=true if we have more registrations to do, false otherwise if (metaChannel.aesKey == null) { /* * Diffie-Hellman-Merkle key exchange for the AES key * http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange */ byte[] ecdhPubKeyBytes = Arrays.copyOfRange(registration.payload, 0, registration.payload.length); ECPublicKeyParameters ecdhPubKey; try { ecdhPubKey = EccPublicKeySerializer.read(new Input(ecdhPubKeyBytes)); } catch (KryoException e) { logger.error("Invalid decode of ECDH public key. Aborting."); shutdown(channel, registration.sessionID); return; } BasicAgreement agreement = new ECDHCBasicAgreement(); agreement.init(metaChannel.ecdhKey.getPrivate()); BigInteger shared = agreement.calculateAgreement(ecdhPubKey); // now we setup our AES key based on our shared secret! (from ECDH) // the shared secret is different each time a connection is made byte[] keySeed = shared.toByteArray(); SHA384Digest sha384 = new SHA384Digest(); byte[] digest = new byte[sha384.getDigestSize()]; sha384.update(keySeed, 0, keySeed.length); sha384.doFinal(digest, 0); metaChannel.aesKey = Arrays.copyOfRange(digest, 0, 32); // 256bit keysize (32 bytes) metaChannel.aesIV = Arrays.copyOfRange(digest, 32, 44); // 96bit blocksize (12 bytes) required by AES-GCM if (invalidAES(metaChannel)) { // abort if something messed up! shutdown(channel, registration.sessionID); return; } Registration outboundRegister = new Registration(metaChannel.sessionId); // do we have any more registrations? outboundRegister.hasMore = registrationWrapper.hasMoreRegistrations(); channel.writeAndFlush(outboundRegister); // wait for ack from the server before registering the next protocol return; } // IN: upgrade=true if we must upgrade this connection if (registration.upgrade) { // this pipeline can now be marked to be upgraded // upgrade the connection to an encrypted connection // this pipeline encoder/decoder can now be upgraded, and the "connection" added upgradeEncoders(channel, metaChannel, remoteAddress); upgradeDecoders(channel, metaChannel); } // IN: hasMore=true if we have more registrations to do, false otherwise if (registration.hasMore) { logger.trace("Starting another protocol registration"); metaChannel.totalProtocols.incrementAndGet(); registrationWrapper.startNextProtocolRegistration(); return; } // // // we only get this when we are 100% done with the registration of all connection types. // // if (!registration.upgraded) { // setup the pipeline with the real connection upgradePipeline(metaChannel, remoteAddress); // we don't verify anything on the CLIENT. We only verify on the server. // we don't support registering NEW classes after the client starts. if (!registrationWrapper.initClassRegistration(channel, registration)) { // abort if something messed up! shutdown(channel, registration.sessionID); } return; } // IN: upgraded=true this means we are ready to connect, and the server is done with it's onConnect calls // we defer the messages until after our own onConnect() is called... // we have to wait for ALL messages to be received, this way we can prevent out-of-order oddities... int protocolsRemaining = metaChannel.totalProtocols.decrementAndGet(); if (protocolsRemaining > 0) { logger.trace("{} done. Waiting for {} more protocols registrations to arrive...", type, protocolsRemaining); return; } // remove the ConnectionWrapper (that was used to upgrade the connection) and cleanup the pipeline // always wait until AFTER the server calls "onConnect", then we do this cleanupPipeline(metaChannel, new Runnable() { @Override public void run() { // this method runs after the "onConnect()" runs and only after all of the channels have be correctly updated // get all of the out of order messages that we missed List<Object> messages = new LinkedList<Object>(); if (metaChannel.tcpChannel != null) { List<Object> list = getOutOfOrderMessagesAndReset(metaChannel.tcpChannel); if (list != null) { logger.trace("Getting deferred TCP messages: {}", list.size()); messages.addAll(list); } } if (metaChannel.udpChannel != null) { List<Object> list = getOutOfOrderMessagesAndReset(metaChannel.udpChannel); if (list != null) { logger.trace("Getting deferred UDP messages: {}", list.size()); messages.addAll(list); } } // now call 'onMessage' in the connection object with our messages! try { ConnectionImpl connection = (ConnectionImpl) metaChannel.connection; for (Object message : messages) { logger.trace(" deferred onMessage({}, {})", connection.id(), message); try { connection.channelRead(null, message); } catch (Exception e) { logger.error("Error running deferred messages!", e); } } } catch (Exception e) { logger.error("Error initialising deferred messages!", e); } } }); }
From source file:dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerServer.java
License:Apache License
@SuppressWarnings("Duplicates") void readServer(final ChannelHandlerContext context, final Channel channel, final Registration registration, final String type, final MetaChannel metaChannel) { final InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress(); // IN: session ID == 0 (start of new connection) // OUT: session ID + public key + ecc parameters (which are a nonce. the SERVER defines what these are) if (registration.sessionID == 0) { // whoa! Didn't send valid public key info! if (invalidPublicKey(registration, type)) { shutdown(channel, registration.sessionID); return; }/*from w ww . j av a2 s .c o m*/ // want to validate the public key used! This is similar to how SSH works, in that once we use a public key, we want to validate // against that ip-address::key pair, so we can better protect against MITM/spoof attacks. if (invalidRemoteAddress(metaChannel, registration, type, remoteAddress)) { // whoa! abort since something messed up! (log and recording if key changed happens inside of validate method) shutdown(channel, registration.sessionID); return; } // save off remote public key. This is ALWAYS the same, where the ECDH changes every time... metaChannel.publicKey = registration.publicKey; // tell the client to continue it's registration process. Registration outboundRegister = new Registration(metaChannel.sessionId); outboundRegister.publicKey = registrationWrapper.getPublicKey(); outboundRegister.eccParameters = CryptoECC .generateSharedParameters(registrationWrapper.getSecureRandom()); channel.writeAndFlush(outboundRegister); return; } // IN: remote ECDH shared payload // OUT: server ECDH shared payload if (metaChannel.aesKey == null) { /* * Diffie-Hellman-Merkle key exchange for the AES key * http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange */ // the ECDH key will ROTATE every 10 minutes, since generating it for EVERY connection is expensive // and since we are combining ECDHE+ECC public/private keys for each connection, other // connections cannot break someone else's connection, since they are still protected by their own private keys. metaChannel.ecdhKey = getEchdKeyOnRotate(registrationWrapper.getSecureRandom()); byte[] ecdhPubKeyBytes = java.util.Arrays.copyOfRange(registration.payload, 0, registration.payload.length); ECPublicKeyParameters ecdhPubKey; try { ecdhPubKey = EccPublicKeySerializer.read(new Input(ecdhPubKeyBytes)); } catch (KryoException e) { logger.error("Invalid decode of ECDH public key. Aborting."); shutdown(channel, registration.sessionID); return; } BasicAgreement agreement = new ECDHCBasicAgreement(); agreement.init(metaChannel.ecdhKey.getPrivate()); BigInteger shared = agreement.calculateAgreement(ecdhPubKey); // now we setup our AES key based on our shared secret! (from ECDH) // the shared secret is different each time a connection is made byte[] keySeed = shared.toByteArray(); SHA384Digest sha384 = new SHA384Digest(); byte[] digest = new byte[sha384.getDigestSize()]; sha384.update(keySeed, 0, keySeed.length); sha384.doFinal(digest, 0); metaChannel.aesKey = Arrays.copyOfRange(digest, 0, 32); // 256bit keysize (32 bytes) metaChannel.aesIV = Arrays.copyOfRange(digest, 32, 44); // 96bit blocksize (12 bytes) required by AES-GCM if (invalidAES(metaChannel)) { // abort if something messed up! shutdown(channel, registration.sessionID); return; } Registration outboundRegister = new Registration(metaChannel.sessionId); Output output = new Output(1024); EccPublicKeySerializer.write(output, (ECPublicKeyParameters) metaChannel.ecdhKey.getPublic()); outboundRegister.payload = output.toBytes(); channel.writeAndFlush(outboundRegister); return; } // NOTE: if we have more registrations, we will "bounce back" that status so the client knows what to do. // IN: hasMore=true if we have more registrations to do, false otherwise // ALWAYS upgrade the connection at this point. // IN: upgraded=false if we haven't upgraded to encryption yet (this will always be the case right after encryption is setup) if (!registration.upgraded) { // upgrade the connection to an encrypted connection registration.upgrade = true; upgradeDecoders(channel, metaChannel); // bounce back to the client so it knows we received it channel.write(registration); // this pipeline encoder/decoder can now be upgraded, and the "connection" added upgradeEncoders(channel, metaChannel, remoteAddress); if (!registration.hasMore) { // we only get this when we are 100% done with the registration of all connection types. // setup the pipeline with the real connection upgradePipeline(metaChannel, remoteAddress); } channel.flush(); return; } // the client will send their class registration data. VERIFY IT IS CORRECT! STATE state = registrationWrapper.verifyClassRegistration(metaChannel, registration); if (state == STATE.ERROR) { // abort! There was an error shutdown(channel, registration.sessionID); return; } else if (state == STATE.WAIT) { return; } // else, continue. // // // we only get this when we are 100% done with the registration of all connection types. // the context is the LAST protocol to be registered // // // remove the ConnectionWrapper (that was used to upgrade the connection) and cleanup the pipeline cleanupPipeline(metaChannel, new Runnable() { @Override public void run() { // this method runs after the "onConnect()" runs and only after all of the channels have be correctly updated // this tells the client we are ready to connect (we just bounce back the original message over ALL protocols) if (metaChannel.tcpChannel != null) { logger.trace("Sending TCP upgraded command"); Registration reg = new Registration(registration.sessionID); reg.upgraded = true; metaChannel.tcpChannel.writeAndFlush(reg); } if (metaChannel.udpChannel != null) { logger.trace("Sending UDP upgraded command"); Registration reg = new Registration(registration.sessionID); reg.upgraded = true; metaChannel.udpChannel.writeAndFlush(reg); } } }); }
From source file:dorkbox.util.crypto.EccTest.java
License:Apache License
@Test public void Ecdh() throws IOException { // test DH key exchange SecureRandom secureRandom = new SecureRandom(); AsymmetricCipherKeyPair key1 = CryptoECC.generateKeyPair(CryptoECC.default_curve, secureRandom); AsymmetricCipherKeyPair key2 = CryptoECC.generateKeyPair(CryptoECC.default_curve, secureRandom); BasicAgreement e1 = new ECDHCBasicAgreement(); BasicAgreement e2 = new ECDHCBasicAgreement(); e1.init(key1.getPrivate()); e2.init(key2.getPrivate());//from ww w. jav a 2 s . c om BigInteger k1 = e1.calculateAgreement(key2.getPublic()); BigInteger k2 = e2.calculateAgreement(key1.getPublic()); if (!k1.equals(k2)) { fail("ECDHC cipher test failed"); } }
From source file:me.grapebaba.hyperledger.fabric.Crypto.java
License:Apache License
public ByteString eciesDecrypt(PrivateKey recipientPrivateKey, ByteString cipherText) { BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) recipientPrivateKey; ECNamedCurveSpec ecNamedCurveSpec = (ECNamedCurveSpec) bcecPrivateKey.getParams(); int level = SecurityLevel.from(ecNamedCurveSpec.getName()).size(); //cipherText = ephemeralPubKeyBytes + encryptedTokBytes + macBytes //ephemeralPubKeyBytes = first ((384+7)/8)*2 + 1 bytes = first 97 bytes //hmac is sha3_384 = 48 bytes or sha3_256 = 32 bytes int ephemeralPubKeyLength = ((level + 7) / 8) * 2 + 1; int hmacLength = level >> 3; int cipherTextLength = cipherText.size(); if (cipherTextLength <= ephemeralPubKeyLength + hmacLength) throw new RuntimeException(String.format("Illegal cipherText length: %d must be > %d", cipherTextLength, ephemeralPubKeyLength + hmacLength)); ByteString ephemeralPubKey = cipherText.substring(0, ephemeralPubKeyLength); ByteString encryptedContent = cipherText.substring(ephemeralPubKeyLength, cipherTextLength - hmacLength); ByteString hmac = cipherText.substring(cipherTextLength - hmacLength); ECPrivateKeyParameters ecdhPrivateKeyParameters; try {/*from w w w . j a va 2 s . co m*/ ecdhPrivateKeyParameters = (ECPrivateKeyParameters) (PrivateKeyFactory .createKey(bcecPrivateKey.getEncoded())); } catch (IOException e) { logger.error("ECIES decrypt load private key exception", e); throw new RuntimeException(e); } ECDomainParameters ecDomainParameters = ecdhPrivateKeyParameters.getParameters(); ECCurve ecCurve = ecDomainParameters.getCurve(); ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters( ecCurve.decodePoint(ephemeralPubKey.toByteArray()), ecDomainParameters); BasicAgreement agree = new ECDHBasicAgreement(); agree.init(ecdhPrivateKeyParameters); byte[] keyAgreement = agree.calculateAgreement(ecPublicKeyParameters).toByteArray(); HKDFParameters hkdfParameters = new HKDFParameters(keyAgreement, null, null); HKDFBytesGenerator hkdfBytesGenerator = new HKDFBytesGenerator(digest); hkdfBytesGenerator.init(hkdfParameters); byte[] hkdfOutputBytes = new byte[AESKEY_LENGTH + HMACKEY_LENGTH]; hkdfBytesGenerator.generateBytes(hkdfOutputBytes, 0, AESKEY_LENGTH + HMACKEY_LENGTH); ByteString hkdfOutput = ByteString.copyFrom(hkdfOutputBytes); ByteString aesKey = hkdfOutput.substring(0, AESKEY_LENGTH); ByteString hmacKey = hkdfOutput.substring(AESKEY_LENGTH, AESKEY_LENGTH + HMACKEY_LENGTH); HMac hMac = new HMac(digest); hMac.init(new KeyParameter(hmacKey.toByteArray())); hMac.update(encryptedContent.toByteArray(), 0, encryptedContent.size()); byte[] recoveredHmac = new byte[hMac.getMacSize()]; hMac.doFinal(recoveredHmac, 0); if (!MessageDigest.isEqual(hmac.toByteArray(), recoveredHmac)) { throw new RuntimeException("HMAC verify failed"); } CFBBlockCipher aesCipher = new CFBBlockCipher(new AESEngine(), BLOCK_BIT_SIZE); ByteString iv = encryptedContent.substring(0, IV_LENGTH); CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(aesKey.toByteArray()), iv.toByteArray()); aesCipher.init(false, ivAndKey); byte[] decryptedBytes = new byte[500]; aesCipher.decryptBlock(encryptedContent.substring(IV_LENGTH).toByteArray(), 0, decryptedBytes, 0); return ByteString.copyFrom(decryptedBytes); }