Example usage for org.bouncycastle.openpgp PGPSignatureGenerator setHashedSubpackets

List of usage examples for org.bouncycastle.openpgp PGPSignatureGenerator setHashedSubpackets

Introduction

In this page you can find the example usage for org.bouncycastle.openpgp PGPSignatureGenerator setHashedSubpackets.

Prototype

public void setHashedSubpackets(PGPSignatureSubpacketVector hashedPcks) 

Source Link

Usage

From source file:alpha.offsync.security.OpenPGPSecurityUtility.java

License:Apache License

@Override
public void sign(final OutputStream outputStream, final InputStream inputStream, final String keyInfo) {
    try {// www . ja v a2  s . co m
        final File keyFile = this.secretKeyRing;
        final char[] pass = this.secretKeyRingPassword;

        final ArmoredOutputStream out = new ArmoredOutputStream(outputStream);

        final PGPSecretKey pgpSec = this.getSignKey(keyInfo); // readSecretKey(new
        // FileInputStream(keyFile));
        final PGPPrivateKey pgpPrivKey = pgpSec.extractPrivateKey(
                new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
        final PGPSignatureGenerator sGen = new PGPSignatureGenerator(
                new BcPGPContentSignerBuilder(pgpSec.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1));

        sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);

        final Iterator it = pgpSec.getPublicKey().getUserIDs();
        if (it.hasNext()) {
            final PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();

            spGen.setSignerUserID(false, (String) it.next());
            sGen.setHashedSubpackets(spGen.generate());
        }

        final PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZLIB);

        final BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out));

        sGen.generateOnePassVersion(false).encode(bOut);

        final PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
        final byte[] buffer = new byte[1 << 16];
        final OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, "", new Date(), buffer);
        int ch = 0;

        while ((ch = inputStream.read()) >= 0) {
            lOut.write(ch);
            sGen.update((byte) ch);
        }

        lGen.close();

        sGen.generate().encode(bOut);
        cGen.close();

        out.close();
    } catch (final FileNotFoundException e) {
        e.printStackTrace();
    } catch (final IOException e) {
        e.printStackTrace();
    } catch (final PGPException e) {
        e.printStackTrace();
    } catch (final SignatureException e) {
        e.printStackTrace();
    }
}

From source file:com.arcusx.simplepgp.PgpDataEncryptor.java

public void encryptAndSign(InputStream dataIn, InputStream recipientPublicKeyFileIn, String dataFileName,
        InputStream senderPrivateKeyFileIn, OutputStream dataOut, boolean isArmoredOutput)
        throws IOException, PGPException {
    PGPCompressedDataGenerator comData = null;
    try {/*from   w  ww  . j  a  va  2 s. c  om*/
        OutputStream out = dataOut;
        PGPPublicKey recipientPublicKey = PgpKeyUtils.readPublicKey(recipientPublicKeyFileIn);

        if (isArmoredOutput) {
            out = new ArmoredOutputStream(out);
        }

        BcPGPDataEncryptorBuilder dataEncryptor = new BcPGPDataEncryptorBuilder(PGPEncryptedData.TRIPLE_DES);
        dataEncryptor.setWithIntegrityPacket(true);
        dataEncryptor.setSecureRandom(new SecureRandom());

        PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(dataEncryptor);
        encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(recipientPublicKey));

        OutputStream encryptedOut = encryptedDataGenerator.open(out, new byte[BUFFER_SIZE]);

        // Initialize compressed data generator
        PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(
                PGPCompressedData.ZIP);
        OutputStream compressedOut = compressedDataGenerator.open(encryptedOut, new byte[BUFFER_SIZE]);

        // Initialize signature generator
        final PGPSecretKey senderSecretKey = PgpKeyUtils.findSecretKey(senderPrivateKeyFileIn);
        PGPPrivateKey privateKey = PgpKeyUtils.getPrivateKeyFrom(senderSecretKey);

        PGPContentSignerBuilder signerBuilder = new BcPGPContentSignerBuilder(
                senderSecretKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);

        PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(signerBuilder);
        signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, privateKey);

        PGPSignatureSubpacketGenerator signatureSubpacketGenerator = new PGPSignatureSubpacketGenerator();
        signatureSubpacketGenerator.setSignerUserID(false, PgpKeyUtils.getUserIdFrom(senderSecretKey));
        signatureGenerator.setHashedSubpackets(signatureSubpacketGenerator.generate());
        signatureGenerator.generateOnePassVersion(false).encode(compressedOut);

        // Initialize literal data generator
        PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator();
        OutputStream literalOut = literalDataGenerator.open(compressedOut, PGPLiteralData.BINARY, dataFileName,
                new Date(), new byte[BUFFER_SIZE]);

        byte[] buf = new byte[BUFFER_SIZE];
        int len;
        while ((len = dataIn.read(buf)) > 0) {
            literalOut.write(buf, 0, len);
            signatureGenerator.update(buf, 0, len);
        }
        dataIn.close();
        literalDataGenerator.close();

        // generate the signature, compress, encrypt and write to the "out" stream
        signatureGenerator.generate().encode(compressedOut);
        compressedDataGenerator.close();
        encryptedDataGenerator.close();
        if (isArmoredOutput) {
            out.close();
        }
    } finally {
        if (comData != null) {
            comData.close();
        }
        IOUtils.closeQuietly(dataOut);
    }
}

From source file:com.geekcommune.identity.EncryptionUtil.java

License:Open Source License

/**
 * Sign the passed in message stream/*w w w .j  a  v a2 s . c  om*/
 */
private void signData(File inFile, OutputStream aOut, PGPPublicKey publicKey, PGPPrivateKey privateKey)
        throws PGPException {
    try {
        PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
        BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(aOut));
        PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();

        PGPSignatureGenerator sGen = new PGPSignatureGenerator(publicKey.getAlgorithm(), PGPUtil.SHA1, "BC");

        sGen.initSign(PGPSignature.BINARY_DOCUMENT, privateKey);

        @SuppressWarnings("unchecked")
        Iterator<String> users = publicKey.getUserIDs();
        if (users.hasNext()) {
            PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
            spGen.setSignerUserID(false, users.next());
            sGen.setHashedSubpackets(spGen.generate());
        }

        sGen.generateOnePassVersion(false).encode(bOut);

        OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, inFile);

        FileInputStream fIn = new FileInputStream(inFile);

        int ch;
        while ((ch = fIn.read()) >= 0) {
            lOut.write(ch);
            sGen.update((byte) ch);
        }

        fIn.close();

        // close() finishes the writing of the literal data and flushes the stream
        // It does not close bOut so this is ok here
        lGen.close();

        // Generate the signature
        sGen.generate().encode(bOut);

        // Must not close bOut here
        bOut.finish();
        bOut.flush();

        cGen.close();
    } catch (PGPException e) {
        throw e;
    } catch (Exception e) {
        throw new PGPException("Error in signing", e);
    }
}

From source file:com.geekcommune.identity.EncryptionUtil.java

License:Open Source License

public PGPSignature makeSignature(byte[] input, PGPPublicKey publicKey, PGPPrivateKey privateKey)
        throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, SignatureException {
    PGPSignatureGenerator sGen = new PGPSignatureGenerator(publicKey.getAlgorithm(), PGPUtil.SHA1, "BC");

    sGen.initSign(PGPSignature.BINARY_DOCUMENT, privateKey);

    @SuppressWarnings("unchecked")
    Iterator<String> users = publicKey.getUserIDs();
    if (users.hasNext()) {
        PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
        spGen.setSignerUserID(false, users.next());
        sGen.setHashedSubpackets(spGen.generate());
    }// w  ww.j  a va 2  s.c om

    for (byte b : input) {
        sGen.update(b);
    }

    return sGen.generate();
}

From source file:com.navnorth.learningregistry.LRSigner.java

License:Apache License

/**
 * Encodes the provided message with the private key and pass phrase set in configuration
 *
 * @param message Message to encode/*from   w ww  .j a va2 s  . c  o  m*/
 * @return Encoded message
 * @throws LRException SIGNING_FAILED if the document cannot be signed, NO_KEY if the key cannot be obtained
 */
private String signEnvelopeData(String message) throws LRException {
    // Throw an exception if any of the required fields are null
    if (passPhrase == null || publicKeyLocation == null || privateKey == null) {
        throw new LRException(LRException.NULL_FIELD);
    }

    // Add the provider here so that after signing, we can remove the provider.
    // This allows using this code from multiple separate class loaders while Bouncy Castle is on a separate class loader
    BouncyCastleProvider provider = new BouncyCastleProvider();
    Security.addProvider(provider);

    try {

        // Get an InputStream for the private key
        InputStream privateKeyStream = getPrivateKeyStream(privateKey);

        // Get an OutputStream for the result
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        ArmoredOutputStream aOut = new ArmoredOutputStream(result);

        // Get the pass phrase
        char[] privateKeyPassword = passPhrase.toCharArray();

        try {
            // Get the private key from the InputStream
            PGPSecretKey sk = readSecretKey(privateKeyStream);
            PGPPrivateKey pk = sk.extractPrivateKey(
                    new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(privateKeyPassword));
            PGPSignatureGenerator sGen = new PGPSignatureGenerator(
                    new JcaPGPContentSignerBuilder(sk.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
                            .setProvider("BC"));
            PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();

            // Clear sign the message
            java.util.Iterator it = sk.getPublicKey().getUserIDs();
            if (it.hasNext()) {
                spGen.setSignerUserID(false, (String) it.next());
                sGen.setHashedSubpackets(spGen.generate());
            }
            aOut.beginClearText(PGPUtil.SHA256);
            sGen.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, pk);
            byte[] msg = message.getBytes();
            sGen.update(msg, 0, msg.length);
            aOut.write(msg, 0, msg.length);
            BCPGOutputStream bOut = new BCPGOutputStream(aOut);
            aOut.endClearText();
            sGen.generate().encode(bOut);
            aOut.close();

            String strResult = result.toString("utf8");

            // for whatever reason, bouncycastle is failing to put a linebreak before "-----BEGIN PGP SIGNATURE"
            strResult = strResult.replaceAll("([a-z0-9])-----BEGIN PGP SIGNATURE-----",
                    "$1\n-----BEGIN PGP SIGNATURE-----");

            return strResult;
        } catch (Exception e) {
            throw new LRException(LRException.SIGNING_FAILED, e);
        } finally {
            try {
                if (privateKeyStream != null) {
                    privateKeyStream.close();
                }

                result.close();
            } catch (IOException e) {
                //Could not close the streams
            }
        }
    } finally {
        Security.removeProvider(provider.getName());
    }
}

From source file:com.verhas.licensor.License.java

License:Open Source License

/**
 * Encode the currently loaded/created license.
 * //from ww w  .  j a v  a 2s.com
 * @param keyPassPhraseString
 *            the pass phrase to the signing key that was loaded.
 * @return the license encoded as ascii string.
 * @throws java.io.IOException
 * @throws java.security.NoSuchAlgorithmException
 * @throws java.security.NoSuchProviderException
 * @throws org.bouncycastle.openpgp.PGPException
 * @throws java.security.SignatureException
 */
public String encodeLicense(final String keyPassPhraseString) throws IOException, NoSuchAlgorithmException,
        NoSuchProviderException, PGPException, SignatureException {

    final char[] keyPassPhrase = keyPassPhraseString.toCharArray();
    final String licensePlain = getLicenseString();
    final ByteArrayOutputStream baOut = new ByteArrayOutputStream();
    final OutputStream out = new ArmoredOutputStream(baOut);

    final PGPPrivateKey pgpPrivKey = key.extractPrivateKey(keyPassPhrase, "BC");
    final PGPSignatureGenerator sGen = new PGPSignatureGenerator(key.getPublicKey().getAlgorithm(),
            hashAlgorithm, "BC");

    sGen.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);

    @SuppressWarnings("unchecked")
    final Iterator<String> it = key.getPublicKey().getUserIDs();
    if (it.hasNext()) {
        final PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();

        spGen.setSignerUserID(false, it.next());
        sGen.setHashedSubpackets(spGen.generate());
    }

    final PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(PGPCompressedData.ZLIB);

    final BCPGOutputStream bOut = new BCPGOutputStream(cGen.open(out));

    sGen.generateOnePassVersion(false).encode(bOut);

    final PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
    final OutputStream lOut = lGen.open(bOut, PGPLiteralData.BINARY, "licenseFileName-Ignored", new Date(),
            new byte[1024]);
    final InputStream fIn = new ByteArrayInputStream(licensePlain.getBytes("utf-8"));
    int ch = 0;
    while ((ch = fIn.read()) >= 0) {
        lOut.write(ch);
        sGen.update((byte) ch);
    }
    lGen.close();
    sGen.generate().encode(bOut);
    cGen.close();
    out.close();
    return new String(baOut.toByteArray());
}

From source file:crypttools.PGPCryptoBC.java

License:Open Source License

public String signData(String data, String passphrase) throws Exception {
    Security.addProvider(new BouncyCastleProvider());
    InputStream keyInputStream = new ByteArrayInputStream(this.armoredSecretKey);
    PGPSecretKey pgpSecretKey = readSecretKey(keyInputStream);
    PGPPrivateKey pgpPrivateKey = pgpSecretKey.extractPrivateKey(
            new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(passphrase.toCharArray()));
    PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
            new JcaPGPContentSignerBuilder(pgpSecretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1)
                    .setProvider("BC"));
    signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, pgpPrivateKey);

    @SuppressWarnings("unchecked")
    Iterator<String> it = pgpSecretKey.getPublicKey().getUserIDs();
    if (it.hasNext()) {
        PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
        spGen.setSignerUserID(false, it.next());
        signatureGenerator.setHashedSubpackets(spGen.generate());
    }//from  w  ww.  ja v  a2  s  .c o m
    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    OutputStream outputStream = new ArmoredOutputStream(byteOutputStream);
    PGPCompressedDataGenerator compressDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.ZLIB);
    BCPGOutputStream bcOutputStream = new BCPGOutputStream(compressDataGenerator.open(outputStream));
    signatureGenerator.generateOnePassVersion(false).encode(bcOutputStream);

    PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator();
    File fileToSign = File.createTempFile("temp", ".scrap");
    FileUtils.writeStringToFile(fileToSign, data);

    OutputStream literalDataGenOutputStream = literalDataGenerator.open(bcOutputStream, PGPLiteralData.BINARY,
            fileToSign);
    FileInputStream fis = new FileInputStream(fileToSign);
    int ch;
    while ((ch = fis.read()) >= 0) {
        literalDataGenOutputStream.write(ch);
        signatureGenerator.update((byte) ch);
    }

    literalDataGenerator.close();
    fis.close();

    signatureGenerator.generate().encode(bcOutputStream);
    compressDataGenerator.close();
    outputStream.close();

    fileToSign.delete();
    return new String(byteOutputStream.toByteArray(), "UTF-8");
}

From source file:de.softwareforge.pgpsigner.commands.SignCommand.java

License:Apache License

@Override
public void executeInteractiveCommand(final String[] args) {

    PGPSignatureGenerator signatureGenerator = null;

    SecretKey signKey = getContext().getSignKey();
    PGPPublicKey pubKey = signKey.getPGPPublicKey();

    try {//from  www . j  a  v a  2  s.  c  o m
        signatureGenerator = new PGPSignatureGenerator(pubKey.getAlgorithm(), PGPUtil.SHA1, "BC");
        signatureGenerator.initSign(PGPSignature.DEFAULT_CERTIFICATION, signKey.getPGPPrivateKey());

        PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator();
        for (Iterator it = pubKey.getUserIDs(); it.hasNext();) {
            subpacketGenerator.setSignerUserID(false, (String) it.next());
            signatureGenerator.setHashedSubpackets(subpacketGenerator.generate());
        }
    } catch (RuntimeException re) {
        throw re;
    } catch (Exception e) {
        System.out.println("Could not generate signature for signing.");
        return;
    }

    for (PublicKey key : getContext().getPartyRing().getVisibleKeys().values()) {

        if (!key.isSigned()) {
            try {
                PGPPublicKey newKey = key.getPGPPublicKey();
                PGPSignature signature = signatureGenerator.generateCertification(newKey);

                for (Iterator it = key.getUserIds(); it.hasNext();) {
                    String userId = (String) it.next();
                    newKey = PGPPublicKey.addCertification(newKey, userId, signature);
                }

                key.setPGPPublicKey(newKey);
                key.setSigned(true);
                System.out.println("Signed Key " + key.getKeyId() + " with " + signKey.getKeyId());

            } catch (RuntimeException re) {
                throw re;
            } catch (Exception e) {
                System.out.println("Could not sign key " + DisplayHelpers.showKey(key) + ", skipping.");
            }
        }
    }
}

From source file:dorkbox.util.crypto.CryptoPGP.java

License:Apache License

/**
 * Creates the signature that will be used to PGP sign data
 *
 * @param secretKeys/*from   ww  w  . j  a  v a 2  s. co  m*/
 *                 these are the secret keys
 * @param password
 *                 this is the password to unlock the secret key
 *
 * @return the signature used to sign data
 *
 * @throws PGPException
 */
private static PGPSignatureGenerator createSignature(List<PGPSecretKey> secretKeys, char[] password,
        int signatureType, boolean generateUserIdSubPacket) throws PGPException {

    PGPSecretKey secretKey = null;
    for (int i = 0; i < secretKeys.size(); i++) {
        secretKey = secretKeys.get(i);

        // we ONLY want the signing master key
        if (!secretKey.isSigningKey() || !secretKey.isMasterKey()) {
            secretKey = null;
        }
    }

    if (secretKey == null) {
        throw new PGPException("Secret key is not the signing master key");
    }

    //            System.err.println("Signing key = " + tmpKey.isSigningKey() +", Master key = " + tmpKey.isMasterKey() + ", UserId = " +
    //                               userId );

    if (password == null) {
        password = new char[0];
    }

    PBESecretKeyDecryptor build = new BcPBESecretKeyDecryptorBuilder(digestCalculatorProvider).build(password);

    SecureRandom random = new SecureRandom();
    BcPGPContentSignerBuilder bcPGPContentSignerBuilder = new BcPGPContentSignerBuilder(
            secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1).setSecureRandom(random);

    PGPSignatureGenerator signature = new PGPSignatureGenerator(bcPGPContentSignerBuilder);
    signature.init(signatureType, secretKey.extractPrivateKey(build));

    Iterator userIds = secretKey.getPublicKey().getUserIDs();

    // use the first userId that matches
    if (userIds.hasNext()) {
        if (generateUserIdSubPacket) {
            PGPSignatureSubpacketGenerator subpacketGenerator = new PGPSignatureSubpacketGenerator();
            subpacketGenerator.setSignerUserID(false, (String) userIds.next());
            signature.setHashedSubpackets(subpacketGenerator.generate());
        } else {
            signature.setHashedSubpackets(null);
        }

        return signature;
    } else {
        throw new PGPException("Did not find specified userId");
    }
}

From source file:eu.mrbussy.security.crypto.pgp.PGPEncryptor.java

License:Open Source License

public void encryptFile(File inputFile, File outputFile)
        throws IOException, NoSuchProviderException, PGPException {
    if (pedg == null) {
        pedg = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, checkIntegrity, new SecureRandom(), "BC");

        try {//  w ww.  jav a  2  s  .c o  m
            pedg.addMethod(publicKey);
        } catch (PGPException e) {
            throw new PGPException("Error when creating PGP encryptino data generator.");
        }
    }
    OutputStream fileOutStream = new FileOutputStream(outputFile);
    if (isArmored) {
        fileOutStream = new ArmoredOutputStream(fileOutStream);
    }

    OutputStream encryptdOutStream = pedg.open(fileOutStream, new byte[1 << 16]);
    PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
    OutputStream compressedOutStream = comData.open(encryptdOutStream);

    try {
        PGPSignatureGenerator sg = null;
        if (isSigning) {
            InputStream keyInputStream = new FileInputStream(new File(signingPrivateKeyFilePath));
            PGPSecretKey secretKey = PGPUtils.findSecretKey(keyInputStream);
            PGPPrivateKey privateKey = secretKey.extractPrivateKey(signingPrivateKeyPassword.toCharArray(),
                    "BC");
            sg = new PGPSignatureGenerator(secretKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1, "BC");
            sg.initSign(PGPSignature.BINARY_DOCUMENT, privateKey);
            Iterator it = secretKey.getPublicKey().getUserIDs();
            if (it.hasNext()) {
                PGPSignatureSubpacketGenerator ssg = new PGPSignatureSubpacketGenerator();
                ssg.setSignerUserID(false, (String) it.next());
                sg.setHashedSubpackets(ssg.generate());
            }
            sg.generateOnePassVersion(false).encode(compressedOutStream);
        }

        PGPLiteralDataGenerator lg = new PGPLiteralDataGenerator();
        OutputStream literalDataOutStream = lg.open(compressedOutStream, PGPLiteralData.BINARY, inputFile);

        byte[] bytes = IOUtils.toByteArray(new FileInputStream(inputFile));

        literalDataOutStream.write(bytes);
        if (isSigning) {
            sg.update(bytes);
            sg.generate().encode(compressedOutStream);
        }
        literalDataOutStream.close();
        lg.close();
        compressedOutStream.close();
        comData.close();
        pedg.close();
        fileOutStream.close();
    } catch (PGPException e) {
        System.err.println(e);
        if (e.getUnderlyingException() != null) {
            e.getUnderlyingException().printStackTrace();
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (SignatureException e) {
        e.printStackTrace();
    }
}