List of usage examples for org.bouncycastle.util Arrays copyOfRange
public static BigInteger[] copyOfRange(BigInteger[] original, int from, int to)
From source file:org.hyperledger.fabric.sdk.MemberServicesImpl.java
License:Open Source License
/** * Process a batch of tcerts after having retrieved them from the TCA. *///from ww w . j a v a 2 s . c om private List<TCert> processTCertBatch(GetTCertBatchRequest req, TCertCreateSetResp resp) throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, CryptoException, IOException { String enrollKey = req.getEnrollment().getKey(); byte[] tCertOwnerKDFKey = resp.getCerts().getKey().toByteArray(); List<Ca.TCert> tCerts = resp.getCerts().getCertsList(); byte[] byte1 = new byte[] { 1 }; byte[] byte2 = new byte[] { 2 }; byte[] tCertOwnerEncryptKey = Arrays.copyOfRange(cryptoPrimitives.calculateMac(tCertOwnerKDFKey, byte1), 0, 32); byte[] expansionKey = cryptoPrimitives.calculateMac(tCertOwnerKDFKey, byte2); List<TCert> tCertBatch = new ArrayList<>(tCerts.size()); // Loop through certs and extract private keys for (Ca.TCert tCert : tCerts) { X509Certificate x509Certificate; try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); x509Certificate = (X509Certificate) cf.generateCertificate(tCert.getCert().newInput()); } catch (Exception ex) { logger.debug("Warning: problem parsing certificate bytes; retrying ... ", ex); continue; } // extract the encrypted bytes from extension attribute byte[] tCertIndexCT = fromDer(x509Certificate.getExtensionValue(TCERT_ENC_TCERT_INDEX)); byte[] tCertIndex = cryptoPrimitives.aesCBCPKCS7Decrypt(tCertOwnerEncryptKey, tCertIndexCT); byte[] expansionValue = cryptoPrimitives.calculateMac(expansionKey, tCertIndex); // compute the private key BigInteger k = new BigInteger(1, expansionValue); BigInteger n = ((ECPrivateKey) cryptoPrimitives.ecdsaKeyFromPrivate(Hex.decode(enrollKey))) .getParameters().getN().subtract(BigInteger.ONE); k = k.mod(n).add(BigInteger.ONE); BigInteger D = ((ECPrivateKey) cryptoPrimitives.ecdsaKeyFromPrivate(Hex.decode(enrollKey))).getD() .add(k); D = D.mod(((ECPrivateKey) cryptoPrimitives.ecdsaKeyFromPrivate(Hex.decode(enrollKey))).getParameters() .getN()); // Put private and public key in returned tcert TCert tcert = new TCert(tCert.getCert().toByteArray(), cryptoPrimitives.ecdsaKeyFromBigInt(D)); tCertBatch.add(tcert); } if (tCertBatch.size() == 0) { throw new RuntimeException("Failed fetching TCertBatch. No valid TCert received."); } return tCertBatch; }
From source file:org.hyperledger.fabric.sdk.security.CryptoPrimitives.java
License:Open Source License
public byte[] eciesDecrypt(KeyPair keyPair, byte[] data) throws CryptoException { try {/* www . j av a 2s . c o m*/ int ek_len = (int) (Math.floor((this.securityLevel + 7) / 8) * 2 + 1); int mk_len = this.securityLevel >> 3; int em_len = data.length - ek_len - mk_len; byte[] ephemeralPublicKeyBytes = Arrays.copyOfRange(data, 0, ek_len); byte[] encryptedMessage = Arrays.copyOfRange(data, ek_len, ek_len + em_len); byte[] tag = Arrays.copyOfRange(data, ek_len + em_len, data.length); // Parsing public key. ECParameterSpec asymmetricKeyParams = generateECParameterSpec(); KeyFactory asymmetricKeyFactory = KeyFactory.getInstance(ASYMMETRIC_KEY_TYPE, SECURITY_PROVIDER); PublicKey ephemeralPublicKey = asymmetricKeyFactory.generatePublic(new ECPublicKeySpec( asymmetricKeyParams.getCurve().decodePoint(ephemeralPublicKeyBytes), asymmetricKeyParams)); // Deriving shared secret. KeyAgreement keyAgreement = KeyAgreement.getInstance(KEY_AGREEMENT_ALGORITHM, SECURITY_PROVIDER); keyAgreement.init(keyPair.getPrivate()); keyAgreement.doPhase(ephemeralPublicKey, true); byte[] sharedSecret = keyAgreement.generateSecret(); // Deriving encryption and mac keys. HKDFBytesGenerator hkdfBytesGenerator = new HKDFBytesGenerator(getHashDigest()); hkdfBytesGenerator.init(new HKDFParameters(sharedSecret, null, null)); byte[] encryptionKey = new byte[SYMMETRIC_KEY_BYTE_COUNT]; hkdfBytesGenerator.generateBytes(encryptionKey, 0, SYMMETRIC_KEY_BYTE_COUNT); byte[] macKey = new byte[MAC_KEY_BYTE_COUNT]; hkdfBytesGenerator.generateBytes(macKey, 0, MAC_KEY_BYTE_COUNT); // Verifying Message Authentication Code (aka mac/tag) byte[] expectedTag = calculateMac(macKey, encryptedMessage); if (!Arrays.areEqual(tag, expectedTag)) { throw new RuntimeException("Bad Message Authentication Code!"); } // Decrypting the message. byte[] iv = Arrays.copyOfRange(encryptedMessage, 0, 16); byte[] encrypted = Arrays.copyOfRange(encryptedMessage, 16, encryptedMessage.length); byte[] output = aesDecrypt(encryptionKey, iv, encrypted); return output; } catch (Exception e) { throw new CryptoException("Could not decrypt the message", e); } }
From source file:org.osgp.pa.dlms.device.Hls5ConnectorLite.java
License:Open Source License
private DecryptedKeys decryptedKeys(final DlmsDevice dlmsDevice) throws TechnicalException, EncrypterException { // Decode the key from Hexstring to bytes byte[] authenticationKey = null; byte[] encryptionKey = null; try {//from w w w .j a v a 2 s . c o m final String validAuthenticationKey = this.dlmsDevice.getAuthKey(); final String validEncryptionKey = this.dlmsDevice.getEncKey(); authenticationKey = Hex.decodeHex(validAuthenticationKey.toCharArray()); encryptionKey = Hex.decodeHex(validEncryptionKey.toCharArray()); } catch (final DecoderException e) { throw new EncrypterException(e); } // Decrypt the key, discard ivBytes byte[] decryptedAuthentication = ENCRYPTION_SRV.decrypt(authenticationKey); byte[] decryptedEncryption = ENCRYPTION_SRV.decrypt(encryptionKey); decryptedAuthentication = Arrays.copyOfRange(decryptedAuthentication, 16, decryptedAuthentication.length); decryptedEncryption = Arrays.copyOfRange(decryptedEncryption, 16, decryptedEncryption.length); return new DecryptedKeys(decryptedAuthentication, decryptedEncryption); }
From source file:org.pieShare.pieShareClient.services.InputTask.java
private synchronized void newPacketReceived() { byte[] bytes = new byte[1024]; bytes = Arrays.copyOfRange(bytes, 0, packet.getLength()); PieLogger.info(this.getClass(), String.format("Input Message: %s", new String(bytes))); JsonObject input = processInput(bytes); if (input.getString("type").equals("connection")) { JsonObject newClient = input.getJsonObject("client"); callback.Handle(newClient);//from ww w . ja v a 2 s .c o m } if (input.getString("type").equals("msg")) { System.out.println("Message Arrived: " + input.getString("msg")); } if (input.getString("type").equals("punch")) { sendTask.send(ackMsg.getBytes(), packet.getAddress().getHostAddress(), packet.getPort()); } if (input.getString("type").equals("ACK")) { sendTask.setACK(true); } }
From source file:org.pieShare.pieShareServer.tasks.LoopHoleListenerTask.java
@Override public void run() { PieLogger.info(this.getClass(), "Listener Started!"); while (run) { byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); try {//from w w w .j a v a 2 s . c om socket.receive(packet); bytes = Arrays.copyOfRange(packet.getData(), 0, packet.getLength()); IUdpMessage msg = (IUdpMessage) serializerService.deserialize(bytes); InetSocketAddress address = new InetSocketAddress(packet.getAddress(), packet.getPort()); msg.setSenderAddress(address); excuterService.handlePieEvent(msg); } catch (IOException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } catch (PieExecutorTaskFactoryException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } catch (SerializerServiceException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } } }
From source file:org.pieShare.pieTools.piePlate.task.LoopHoleListenerTask.java
@Override public void run() { while (run) { byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); try {//ww w. j a va 2s.co m socket.receive(packet); bytes = Arrays.copyOfRange(packet.getData(), 0, packet.getLength()); PieLogger.info(this.getClass(), String.format("Message Arrived: %s", new String(bytes))); IUdpMessage msg = (IUdpMessage) serializerService.deserialize(bytes); InetSocketAddress address = new InetSocketAddress(packet.getAddress(), packet.getPort()); msg.setSenderAddress(address); excuterService.handlePieEvent(msg); } catch (IOException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } catch (PieExecutorTaskFactoryException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } catch (SerializerServiceException ex) { PieLogger.error(this.getClass(), "Error receiving message.", ex); } } }
From source file:org.red5.server.net.rtmp.codec.RTMPMinaProtocolDecoder.java
License:Open Source License
/** {@inheritDoc} */ public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws ProtocolCodecException { // get the connection from the session String sessionId = (String) session.getAttribute(RTMPConnection.RTMP_SESSION_ID); log.trace("Session id: {}", sessionId); // connection verification routine @SuppressWarnings("unchecked") IConnectionManager<RTMPConnection> connManager = (IConnectionManager<RTMPConnection>) ((WeakReference<?>) session .getAttribute(RTMPConnection.RTMP_CONN_MANAGER)).get(); RTMPConnection conn = (RTMPConnection) connManager.getConnectionBySessionId(sessionId); RTMPConnection connLocal = (RTMPConnection) Red5.getConnectionLocal(); if (connLocal == null || !conn.getSessionId().equals(connLocal.getSessionId())) { if (log.isDebugEnabled() && connLocal != null) { log.debug("Connection local didn't match session"); }/*from w ww .j a v a 2 s .c om*/ } if (conn != null) { // set the connection to local if its referred to by this session Red5.setConnectionLocal(conn); // create a buffer and store it on the session IoBuffer buf = (IoBuffer) session.getAttribute("buffer"); if (buf == null) { buf = IoBuffer.allocate(in.limit()); buf.setAutoExpand(true); session.setAttribute("buffer", buf); } // copy incoming into buffer buf.put(in); buf.flip(); if (log.isTraceEnabled()) { log.trace("Buffer before: {}", Hex.encodeHexString(Arrays.copyOfRange(buf.array(), buf.position(), buf.limit()))); log.trace("Buffers info before: buf.position {}, buf.limit {}, buf.remaining {}", new Object[] { buf.position(), buf.limit(), buf.remaining() }); } // get the connections decoder lock final Semaphore lock = conn.getDecoderLock(); try { // acquire the decoder lock //log.trace("Decoder lock acquiring.. {}", sessionId); lock.acquire(); log.trace("Decoder lock acquired {}", sessionId); // construct any objects from the decoded bugger List<?> objects = decoder.decodeBuffer(conn, buf); log.trace("Decoded: {}", objects); if (objects != null) { int writeCount = 0; for (Object object : objects) { out.write(object); writeCount++; } log.trace("Wrote {} objects", writeCount); } } catch (Exception e) { log.error("Error during decode", e); } finally { log.trace("Decoder lock releasing.. {}", sessionId); lock.release(); // clear local Red5.setConnectionLocal(null); } if (log.isTraceEnabled()) { log.trace("Buffer after: {}", Hex.encodeHexString(Arrays.copyOfRange(buf.array(), buf.position(), buf.limit()))); log.trace("Buffers info after: buf.position {}, buf.limit {}, buf.remaining {}", new Object[] { buf.position(), buf.limit(), buf.remaining() }); } } else { log.debug("Closing and skipping decode for unregistered connection: {}", sessionId); session.closeNow(); log.debug("Session closing: {} reading: {} writing: {}", session.isClosing(), session.isReadSuspended(), session.isWriteSuspended()); } }
From source file:org.sufficientlysecure.keychain.experimental.WordConfirm.java
License:Open Source License
public static String getWords(Context context, byte[] fingerprintBlob) { ArrayList<String> words = new ArrayList<>(); BufferedReader reader = null; try {//ww w.jav a 2 s .c o m reader = new BufferedReader( new InputStreamReader(context.getResources().openRawResource(R.raw.fp_word_list), "UTF-8")); String line = reader.readLine(); while (line != null) { words.add(line); line = reader.readLine(); } } catch (IOException e) { throw new RuntimeException("IOException", e); } finally { if (reader != null) { try { reader.close(); } catch (IOException ignored) { } } } String fingerprint = ""; // NOTE: 160 bit SHA-1 truncated to 156 bit byte[] fingerprintBlobTruncated = Arrays.copyOfRange(fingerprintBlob, 0, 156 / 8); // TODO: implement key stretching to minimize fp length? // BitSet bits = BitSet.valueOf(fingerprintBlob); // min API 19 and little endian! BitSet bits = bitSetToByteArray(fingerprintBlobTruncated); Log.d(Constants.TAG, "bits: " + bits.toString()); final int CHUNK_SIZE = 13; final int LAST_CHUNK_INDEX = fingerprintBlobTruncated.length * 8 / CHUNK_SIZE; // 12 Log.d(Constants.TAG, "LAST_CHUNK_INDEX: " + LAST_CHUNK_INDEX); int from = 0; int to = CHUNK_SIZE; for (int i = 0; i < (LAST_CHUNK_INDEX + 1); i++) { Log.d(Constants.TAG, "from: " + from + " to: " + to); BitSet setIndex = bits.get(from, to); int wordIndex = (int) bitSetToLong(setIndex); // int wordIndex = (int) setIndex.toLongArray()[0]; // min API 19 fingerprint += words.get(wordIndex); if (i != LAST_CHUNK_INDEX) { // line break every 3 words if (to % (CHUNK_SIZE * 3) == 0) { fingerprint += "\n"; } else { fingerprint += " "; } } from = to; to += CHUNK_SIZE; } return fingerprint; }
From source file:org.sufficientlysecure.keychain.securitytoken.SCP11bSecureMessaging.java
License:Open Source License
public static void establish(final SecurityTokenHelper t, final Context ctx) throws SecureMessagingException, IOException { final int keySize = t.getOpenPgpCapabilities().getSMAESKeySize(); t.clearSecureMessaging();/*from www .j av a 2s. c o m*/ if ((keySize != 16) && (keySize != 32)) { throw new SecureMessagingException("invalid key size"); } CommandAPDU cmd; ResponseAPDU resp; Iso7816TLV[] tlvs; // retrieving key algorithm cmd = new CommandAPDU(0, (byte) 0xCA, (byte) 0x00, OPENPGP_SECURE_MESSAGING_KEY_ATTRIBUTES_TAG, SecurityTokenHelper.MAX_APDU_NE_EXT); resp = t.communicate(cmd); if (resp.getSW() != SecurityTokenHelper.APDU_SW_SUCCESS) { throw new SecureMessagingException("failed to retrieve secure messaging key attributes"); } tlvs = Iso7816TLV.readList(resp.getData(), true); if ((tlvs == null) || (tlvs.length != 1) || ((byte) tlvs[0].mT != OPENPGP_SECURE_MESSAGING_KEY_ATTRIBUTES_TAG)) { throw new SecureMessagingException("invalid format of secure messaging key attributes"); } final KeyFormat kf = KeyFormat.fromBytes(tlvs[0].mV); if (kf.keyFormatType() != KeyFormat.KeyFormatType.ECKeyFormatType) { throw new SecureMessagingException("invalid format of secure messaging key"); } final ECKeyFormat eckf = (ECKeyFormat) kf; if (eckf.getCurveOID() == null) { throw new SecureMessagingException("unsupported curve"); } try { ECPublicKey pkcard = null; final Preferences prefs = Preferences.getPreferences(ctx); if (prefs != null && prefs.getExperimentalSmartPGPAuthoritiesEnable()) { // retrieving certificate cmd = new CommandAPDU(0, (byte) 0xA5, (byte) 0x03, (byte) 0x04, new byte[] { (byte) 0x60, (byte) 0x04, (byte) 0x5C, (byte) 0x02, (byte) 0x7F, (byte) 0x21 }); resp = t.communicate(cmd); if (resp.getSW() != SecurityTokenHelper.APDU_SW_SUCCESS) { throw new SecureMessagingException("failed to select secure messaging certificate"); } cmd = new CommandAPDU(0, (byte) 0xCA, (byte) 0x7F, (byte) 0x21, SecurityTokenHelper.MAX_APDU_NE_EXT); resp = t.communicate(cmd); if (resp.getSW() != SecurityTokenHelper.APDU_SW_SUCCESS) { throw new SecureMessagingException("failed to retrieve secure messaging certificate"); } pkcard = verifyCertificate(ctx, eckf, resp.getData()); } else { // retrieving public key cmd = new CommandAPDU(0, (byte) 0x47, (byte) 0x81, (byte) 0x00, OPENPGP_SECURE_MESSAGING_KEY_CRT, SecurityTokenHelper.MAX_APDU_NE_EXT); resp = t.communicate(cmd); if (resp.getSW() != SecurityTokenHelper.APDU_SW_SUCCESS) { throw new SecureMessagingException("failed to retrieve secure messaging public key"); } tlvs = Iso7816TLV.readList(resp.getData(), true); if ((tlvs == null) || (tlvs.length != 1) || ((short) tlvs[0].mT != (short) 0x7f49)) { throw new SecureMessagingException("invalid format of secure messaging key"); } tlvs = Iso7816TLV.readList(tlvs[0].mV, true); if ((tlvs == null) || (tlvs.length != 1) || ((byte) tlvs[0].mT != (byte) 0x86)) { throw new SecureMessagingException("invalid format of secure messaging key"); } pkcard = newECDHPublicKey(eckf, tlvs[0].mV); } if (pkcard == null) { throw new SecureMessagingException("No key in token for secure messaging"); } final KeyPair ekoce = generateECDHKeyPair(eckf); final ECPublicKey epkoce = (ECPublicKey) ekoce.getPublic(); final ECPrivateKey eskoce = (ECPrivateKey) ekoce.getPrivate(); final byte[] crt_template = new byte[] { (byte) 0xA6, (byte) 0x0D, (byte) 0x90, (byte) 0x02, (byte) 0x11, (byte) 0x00, (byte) 0x95, (byte) 0x01, (byte) 0x3C, (byte) 0x80, (byte) 0x01, (byte) 0x88, (byte) 0x81, (byte) 0x01, (byte) keySize, (byte) 0x5F, (byte) 0x49 }; int csize = (int) Math.ceil(epkoce.getParams().getCurve().getField().getFieldSize() / 8.0); ByteArrayOutputStream pkout = new ByteArrayOutputStream(), bout = new ByteArrayOutputStream(); pkout.write((byte) 0x04); SecurityTokenUtils.writeBits(pkout, epkoce.getW().getAffineX(), csize); SecurityTokenUtils.writeBits(pkout, epkoce.getW().getAffineY(), csize); bout.write(crt_template); bout.write(SecurityTokenUtils.encodeLength(pkout.size())); pkout.writeTo(bout); pkout = bout; // internal authenticate cmd = new CommandAPDU(0, (byte) 0x88, (byte) 0x01, (byte) 0x0, pkout.toByteArray(), SecurityTokenHelper.MAX_APDU_NE_EXT); resp = t.communicate(cmd); if (resp.getSW() != SecurityTokenHelper.APDU_SW_SUCCESS) { throw new SecureMessagingException("failed to initiate internal authenticate"); } tlvs = Iso7816TLV.readList(resp.getData(), true); if ((tlvs == null) || (tlvs.length != 2) || (tlvs[0].mT == tlvs[1].mT)) { throw new SecureMessagingException("invalid internal authenticate response"); } byte[] receipt = null; ECPublicKey epkcard = null; for (int i = 0; i < tlvs.length; ++i) { switch (tlvs[i].mT) { case 0x86: if (tlvs[i].mL != AES_BLOCK_SIZE) { throw new SecureMessagingException("invalid size for receipt"); } receipt = tlvs[i].mV; break; case 0x5F49: epkcard = newECDHPublicKey(eckf, tlvs[i].mV); break; default: throw new SecureMessagingException("unexpected data in internal authenticate response"); } } final KeyAgreement ecdhKa = KeyAgreement.getInstance(SCP11B_KEY_AGREEMENT_ALGO, PROVIDER); bout = new ByteArrayOutputStream(); //compute ShSe ecdhKa.init(eskoce); ecdhKa.doPhase(epkcard, true); bout.write(ecdhKa.generateSecret()); //compute ShSs ecdhKa.init(eskoce); ecdhKa.doPhase(pkcard, true); bout.write(ecdhKa.generateSecret()); csize = bout.size() + 3; bout.write(new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, crt_template[8], crt_template[11], (byte) keySize }); byte[] shs = bout.toByteArray(); //key derivation final MessageDigest h = MessageDigest.getInstance(SCP11B_KEY_DERIVATION_ALGO, PROVIDER); bout = new ByteArrayOutputStream(); while (bout.size() < 4 * keySize) { ++shs[csize]; bout.write(h.digest(shs)); } shs = bout.toByteArray(); final byte[] rkey = Arrays.copyOfRange(shs, 0, keySize); final byte[] sEnc = Arrays.copyOfRange(shs, keySize, 2 * keySize); final byte[] sMac = Arrays.copyOfRange(shs, 2 * keySize, 3 * keySize); final byte[] sRmac = Arrays.copyOfRange(shs, 3 * keySize, 4 * keySize); //receipt computation final Mac mac = Mac.getInstance(SCP11_MAC_ALGO, PROVIDER); mac.init(new SecretKeySpec(rkey, SCP11_SYMMETRIC_ALGO)); shs = resp.getData(); mac.update(pkout.toByteArray()); mac.update(shs, 0, shs.length - 2 - AES_BLOCK_SIZE); shs = mac.doFinal(); for (int i = 0; i < AES_BLOCK_SIZE; ++i) { if (shs[i] != receipt[i]) { throw new SecureMessagingException("corrupted receipt!"); } } final SCP11bSecureMessaging sm = new SCP11bSecureMessaging(); sm.setKeys(sEnc, sMac, sRmac, receipt); t.setSecureMessaging(sm); } catch (InvalidKeySpecException e) { throw new SecureMessagingException("invalid key specification : " + e.getMessage()); } catch (NoSuchAlgorithmException e) { throw new SecureMessagingException("unknown EC key algorithm : " + e.getMessage()); } catch (InvalidParameterSpecException e) { throw new SecureMessagingException("invalid ECDH parameters : " + e.getMessage()); } catch (NoSuchProviderException e) { throw new SecureMessagingException("unknown provider " + PROVIDER); } catch (InvalidAlgorithmParameterException e) { throw new SecureMessagingException("invalid algorithm parameters : " + e.getMessage()); } catch (InvalidKeyException e) { throw new SecureMessagingException("invalid key : " + e.getMessage()); } catch (IllegalArgumentException e) { throw new SecureMessagingException("illegal argument (" + e.getMessage() + ")"); } }
From source file:org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection.java
License:Open Source License
/** * Call DECIPHER command/* w w w .jav a2s .c o m*/ * * @param encryptedSessionKey the encoded session key * @param publicKey * @return the decoded session key */ public byte[] decryptSessionKey(@NonNull byte[] encryptedSessionKey, CanonicalizedPublicKey publicKey) throws IOException { final KeyFormat kf = mOpenPgpCapabilities.getFormatForKeyType(KeyType.ENCRYPT); if (!mPw1ValidatedForDecrypt) { verifyPinForOther(); } byte[] data; byte[] dataLen; int pLen = 0; X9ECParameters x9Params; switch (kf.keyFormatType()) { case RSAKeyFormatType: data = Arrays.copyOfRange(encryptedSessionKey, 2, encryptedSessionKey.length); if (data[0] != 0) { data = Arrays.prepend(data, (byte) 0x00); } break; case ECKeyFormatType: pLen = ((((encryptedSessionKey[0] & 0xff) << 8) + (encryptedSessionKey[1] & 0xff)) + 7) / 8; data = new byte[pLen]; System.arraycopy(encryptedSessionKey, 2, data, 0, pLen); final ECKeyFormat eckf = (ECKeyFormat) kf; x9Params = NISTNamedCurves.getByOID(eckf.getCurveOID()); final ECPoint p = x9Params.getCurve().decodePoint(data); if (!p.isValid()) { throw new CardException("Invalid EC point!"); } data = p.getEncoded(false); if (data.length < 128) { dataLen = new byte[] { (byte) data.length }; } else { dataLen = new byte[] { (byte) 0x81, (byte) data.length }; } data = Arrays.concatenate(Hex.decode("86"), dataLen, data); if (data.length < 128) { dataLen = new byte[] { (byte) data.length }; } else { dataLen = new byte[] { (byte) 0x81, (byte) data.length }; } data = Arrays.concatenate(Hex.decode("7F49"), dataLen, data); if (data.length < 128) { dataLen = new byte[] { (byte) data.length }; } else { dataLen = new byte[] { (byte) 0x81, (byte) data.length }; } data = Arrays.concatenate(Hex.decode("A6"), dataLen, data); break; default: throw new CardException("Unknown encryption key type!"); } CommandApdu command = commandFactory.createDecipherCommand(data); ResponseApdu response = communicate(command); if (!response.isSuccess()) { throw new CardException("Deciphering with Security token failed on receive", response.getSw()); } switch (mOpenPgpCapabilities.getFormatForKeyType(KeyType.ENCRYPT).keyFormatType()) { case RSAKeyFormatType: return response.getData(); /* From 3.x OpenPGP card specification : In case of ECDH the card supports a partial decrypt only. With its own private key and the given public key the card calculates a shared secret in compliance with the Elliptic Curve Key Agreement Scheme from Diffie-Hellman. The shared secret is returned in the response, all other calculation for deciphering are done outside of the card. The shared secret obtained is a KEK (Key Encryption Key) that is used to wrap the session key. From rfc6637#section-13 : This document explicitly discourages the use of algorithms other than AES as a KEK algorithm. */ case ECKeyFormatType: data = response.getData(); final byte[] keyEnc = new byte[encryptedSessionKey[pLen + 2]]; System.arraycopy(encryptedSessionKey, 2 + pLen + 1, keyEnc, 0, keyEnc.length); try { final MessageDigest kdf = MessageDigest .getInstance(MessageDigestUtils.getDigestName(publicKey.getSecurityTokenHashAlgorithm())); kdf.update(new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 1 }); kdf.update(data); kdf.update(publicKey.createUserKeyingMaterial(fingerprintCalculator)); final byte[] kek = kdf.digest(); final Cipher c = Cipher.getInstance("AESWrap"); c.init(Cipher.UNWRAP_MODE, new SecretKeySpec(kek, 0, publicKey.getSecurityTokenSymmetricKeySize() / 8, "AES")); final Key paddedSessionKey = c.unwrap(keyEnc, "Session", Cipher.SECRET_KEY); Arrays.fill(kek, (byte) 0); return PGPPad.unpadSessionData(paddedSessionKey.getEncoded()); } catch (NoSuchAlgorithmException e) { throw new CardException("Unknown digest/encryption algorithm!"); } catch (NoSuchPaddingException e) { throw new CardException("Unknown padding algorithm!"); } catch (PGPException e) { throw new CardException(e.getMessage()); } catch (InvalidKeyException e) { throw new CardException("Invalid KEK!"); } default: throw new CardException("Unknown encryption key type!"); } }