Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You 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 org.apache.tomcat.util.net.jsse.openssl;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
Class in charge with parsing openSSL expressions to define a list of ciphers.
 
 public class OpenSSLCipherConfigurationParser {

    
System property key to define the DEFAULT ciphers.
 
     public static final String DEFAULT_EXPRESSION_KEY = "openssl.default.ciphers";
 
     private static boolean initialized = false;
 
     private static final String SEPARATOR = ":|,| ";
    
If ! is used then the ciphers are permanently deleted from the list. The ciphers deleted can never reappear in the list even if they are explicitly stated.
 
     private static final String EXCLUDE = "!";
    
If - is used then the ciphers are deleted from the list, but some or all of the ciphers can be added again by later options.
 
     private static final String DELETE = "-";
    
If + is used then the ciphers are moved to the end of the list. This option doesn't add any new ciphers it just moves matching existing ones.
 
     private static final String TO_END = "+";
     
Lists of cipher suites can be combined in a single cipher string using the + character. This is used as a logical and operation. For example SHA1+DES represents all cipher suites containing the SHA1 and the DES algorithms.
 
     private static final String AND = "+";
    
All ciphers by their openssl alias name.
 
     private static final Map<StringList<Cipher>> aliases = new LinkedHashMap<StringList<Cipher>>();

    
the 'NULL' ciphers that is those offering no encryption. Because these offer no encryption at all and are a security risk they are disabled unless explicitly included.
 
     private static final String eNULL = "eNULL";
    
The cipher suites offering no authentication. This is currently the anonymous DH algorithms. T These cipher suites are vulnerable to a 'man in the middle' attack and so their use is normally discouraged.
 
     private static final String aNULL = "aNULL";

    
'high' encryption cipher suites. This currently means those with key lengths larger than 128 bits, and some cipher suites with 128-bit keys.
 
     private static final String HIGH = "HIGH";
    
'medium' encryption cipher suites, currently some of those using 128 bit encryption.
 
     private static final String MEDIUM = "MEDIUM";
    
'low' encryption cipher suites, currently those using 64 or 56 bit encryption algorithms but excluding export cipher suites.
 
     private static final String LOW = "LOW";
    
Export encryption algorithms. Including 40 and 56 bits algorithms.
 
    private static final String EXPORT = "EXPORT";
    
40 bit export encryption algorithms.
    private static final String EXPORT40 = "EXPORT40";
    
56 bit export encryption algorithms.
    private static final String EXPORT56 = "EXPORT56";
    
Cipher suites using RSA key exchange.
    private static final String kRSA = "kRSA";
    
Cipher suites using RSA authentication.
    private static final String aRSA = "aRSA";
    
Cipher suites using RSA for key exchange Despite what the docs say, RSA is equivalent to kRSA.
    private static final String RSA = "RSA";
    
Cipher suites using ephemeral DH key agreement.
    private static final String kEDH = "kEDH";
    
Cipher suites using ephemeral DH key agreement.
    private static final String kDHE = "kDHE";
    
Cipher suites using ephemeral DH key agreement. equivalent to kEDH:-ADH
    private static final String EDH = "EDH";
    
Cipher suites using ephemeral DH key agreement. equivalent to kEDH:-ADH
    private static final String DHE = "DHE";
    
Cipher suites using DH key agreement and DH certificates signed by CAs with RSA keys.
    private static final String kDHr = "kDHr";
    
Cipher suites using DH key agreement and DH certificates signed by CAs with DSS keys.
    private static final String kDHd = "kDHd";
    
Cipher suites using DH key agreement and DH certificates signed by CAs with RSA or DSS keys.
    private static final String kDH = "kDH";
    
Cipher suites using fixed ECDH key agreement signed by CAs with RSA keys.
    private static final String kECDHr = "kECDHr";
    
Cipher suites using fixed ECDH key agreement signed by CAs with ECDSA keys.
    private static final String kECDHe = "kECDHe";
    
Cipher suites using fixed ECDH key agreement signed by CAs with RSA and ECDSA keys or either respectively.
    private static final String kECDH = "kECDH";
    
Cipher suites using ephemeral ECDH key agreement, including anonymous cipher suites.
    private static final String kEECDH = "kEECDH";
    
Cipher suites using ephemeral ECDH key agreement, excluding anonymous cipher suites. Same as "kEECDH:-AECDH"
    private static final String EECDH = "EECDH";
    
Cipher suitesusing ECDH key exchange, including anonymous, ephemeral and fixed ECDH.
    private static final String ECDH = "ECDH";
    
Cipher suites using ephemeral ECDH key agreement, including anonymous cipher suites.
    private static final String kECDHE = "kECDHE";
    
Cipher suites using authenticated ephemeral ECDH key agreement
    private static final String ECDHE = "ECDHE";
    
Cipher suites using authenticated ephemeral ECDH key agreement
    private static final String EECDHE = "EECDHE";
    
Anonymous Elliptic Curve Diffie Hellman cipher suites.
    private static final String AECDH = "AECDH";
    
Cipher suites using DSS authentication, i.e. the certificates carry DSS keys.
    private static final String aDSS = "aDSS";
    
Cipher suites effectively using DH authentication, i.e. the certificates carry DH keys.
    private static final String aDH = "aDH";
    
Cipher suites effectively using ECDH authentication, i.e. the certificates carry ECDH keys.
    private static final String aECDH = "aECDH";
    
Cipher suites effectively using ECDSA authentication, i.e. the certificates carry ECDSA keys.
    private static final String aECDSA = "aECDSA";
    
Cipher suites effectively using ECDSA authentication, i.e. the certificates carry ECDSA keys.
    private static final String ECDSA = "ECDSA";
    
Ciphers suites using FORTEZZA key exchange algorithms.
    private static final String kFZA = "kFZA";
    
Ciphers suites using FORTEZZA authentication algorithms.
    private static final String aFZA = "aFZA";
    
Ciphers suites using FORTEZZA encryption algorithms.
    private static final String eFZA = "eFZA";
    
Ciphers suites using all FORTEZZA algorithms.
    private static final String FZA = "FZA";
    
TLS v1.2 cipher suites. Note: there are no cipher suites specific to TLS v1.1.
    private static final String TLSv1_2 = "TLSv1.2";
    
TLS v1.0 cipher suites.
    private static final String TLSv1 = "TLSv1";
    
SSL v2.0 cipher suites.
    private static final String SSLv2 = "SSLv2";
    
SSL v3.0 cipher suites.
    private static final String SSLv3 = "SSLv3";
    
Cipher suites using DH, including anonymous DH, ephemeral DH and fixed DH.
    private static final String DH = "DH";
    
Anonymous DH cipher suites.
    private static final String ADH = "ADH";
    
Cipher suites using 128 bit AES.
    private static final String AES128 = "AES128";
    
Cipher suites using 256 bit AE.
    private static final String AES256 = "AES256";
    
Cipher suites using either 128 or 256 bit AES.
    private static final String AES = "AES";
    
AES in Galois Counter Mode (GCM): these cipher suites are only supported in TLS v1.2.
    private static final String AESGCM = "AESGCM";
    
Cipher suites using 128 bit CAMELLIA.
    private static final String CAMELLIA128 = "CAMELLIA128";
    
Cipher suites using 256 bit CAMELLIA.
    private static final String CAMELLIA256 = "CAMELLIA256";
    
Cipher suites using either 128 or 256 bit CAMELLIA.
    private static final String CAMELLIA = "CAMELLIA";
    
Cipher suites using triple DES.
    private static final String TRIPLE_DES = "3DES";
    
Cipher suites using DES (not triple DES).
    private static final String DES = "DES";
    
Cipher suites using RC4.
    private static final String RC4 = "RC4";
    
Cipher suites using RC2.
    private static final String RC2 = "RC2";
    
Cipher suites using IDEA.
    private static final String IDEA = "IDEA";
    
Cipher suites using SEED.
    private static final String SEED = "SEED";
    
Cipher suites using MD5.
    private static final String MD5 = "MD5";
    
Cipher suites using SHA1.
    private static final String SHA1 = "SHA1";
    
Cipher suites using SHA1.
    private static final String SHA = "SHA";
    
Cipher suites using SHA256.
    private static final String SHA256 = "SHA256";
    
Cipher suites using SHA384.
    private static final String SHA384 = "SHA384";
    
Cipher suites using KRB5.
    private static final String KRB5 = "KRB5";
    
Cipher suites using GOST R 34.10 (either 2001 or 94) for authentication.
    private static final String aGOST = "aGOST";
    
Cipher suites using GOST R 34.10-2001 for authentication.
    private static final String aGOST01 = "aGOST01";
    
Cipher suites using GOST R 34.10-94 authentication (note that R 34.10-94 standard has been expired so use GOST R 34.10-2001)
    private static final String aGOST94 = "aGOST94";
    
Cipher suites using using VKO 34.10 key exchange, specified in the RFC 4357.
    private static final String kGOST = "kGOST";
    
Cipher suites, using HMAC based on GOST R 34.11-94.
    private static final String GOST94 = "GOST94";
    
Cipher suites using GOST 28147-89 MAC instead of HMAC.
    private static final String GOST89MAC = "GOST89MAC";
    
Cipher suites using pre-shared keys (PSK).
    private static final String PSK = "PSK";
    private static final String DEFAULT = "DEFAULT";
    private static final String COMPLEMENTOFDEFAULT = "COMPLEMENTOFDEFAULT";
    private static final String ALL = "ALL";
    private static final String COMPLEMENTOFALL = "COMPLEMENTOFALL";
    private static final void init() {
        for (Cipher cipher : Cipher.values()) {
            String alias = cipher.getOpenSSLAlias();
            if (.containsKey(alias)) {
                .get(alias).add(cipher);
            } else {
                List<Cipherlist = new ArrayList<Cipher>();
                list.add(cipher);
                .put(aliaslist);
            }
            .put(cipher.name(), Collections.singletonList(cipher));
        }
        List<CipherallCiphersList = Arrays.asList(Cipher.values());
        Collections.reverse(allCiphersList);
        LinkedHashSet<CipherallCiphers = defaultSort(new LinkedHashSet<Cipher>(allCiphersList));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        LinkedHashSet<Cipherall = new LinkedHashSet<Cipher>(allCiphers);
        remove(all);
        addListAlias(all);
        addListAlias(filterByEncryptionLevel(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryptionLevel(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryptionLevel(allCiphers, Collections.singleton(.)));
        .put("EXP".get());
        addListAlias(filterByEncryptionLevel(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryptionLevel(allCiphers, Collections.singleton(.)));
        .put("NULL".get());
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        // Despite what the docs say, RSA is equivalent to kRSA
        .put(.get());
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        Set<Cipheredh = filterByKeyExchange(allCiphers, Collections.singleton(.));
        edh.removeAll(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(edh);
        addListAlias(edh);
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphersnew HashSet<KeyExchange>(Arrays.asList(..))));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        .put(.get());
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        .put(.get());
        Set<Ciphereecdh = filterByKeyExchange(allCiphers, Collections.singleton(.));
        eecdh.removeAll(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(eecdh);
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        .put("DSS".get());
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        Set<Cipheraecdh = filterByKeyExchange(allCiphers, Collections.singleton(.));
        addListAlias(filterByAuthentication(aecdh, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        .put(.get());
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filter(allCiphersnull, Collections.singleton(.), Collections.singleton(.), Collections.singleton(.), nullnull));
        addListAlias(filterByProtocol(allCiphers, Collections.singleton(.)));
        addListAlias("TLSv1.1"filterByProtocol(allCiphers, Collections.singleton(.)));
        addListAlias(filterByProtocol(allCiphersnew HashSet<Protocol>(Arrays.asList(..))));
        .put(.get());
        addListAlias(filterByProtocol(allCiphers, Collections.singleton(.)));
        Set<Cipheradh = filterByKeyExchange(allCiphers, Collections.singleton(.));
        adh.retainAll(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(adh);
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByEncryption(allCiphers, Collections.singleton(.)));
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        .put(.get());
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(filterByAuthentication(allCiphers, Collections.singleton(.)));
        addListAlias(filterByKeyExchange(allCiphers, Collections.singleton(.)));
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        addListAlias(filterByMessageDigest(allCiphers, Collections.singleton(.)));
        addListAlias(filter(allCiphersnull, Collections.singleton(.), Collections.singleton(.), nullnullnull));
        addListAlias(filter(allCiphersnull, Collections.singleton(.), Collections.singleton(.), nullnullnull));
         = true;
        // Despite what the OpenSSL docs say, DEFAULT also excludes SSLv2
        String defaultExpression = System.getProperty("ALL:!eNULL:!aNULL:!SSLv2");
        addListAlias(parse(defaultExpression));
        // COMPLEMENTOFDEFAULT is also not exactly as defined by the docs
        Set<CiphercomplementOfDefault = filterByKeyExchange(allnew HashSet<KeyExchange>(Arrays.asList(.,.)));
        complementOfDefault = filterByAuthentication(complementOfDefault, Collections.singleton(.));
        complementOfDefault.removeAll(.get());
        addListAlias(complementOfDefault);
    }
    static void addListAlias(String aliasSet<Cipherciphers) {
        .put(aliasnew ArrayList<Cipher>(ciphers));
    }
    static void moveToEnd(final LinkedHashSet<Cipherciphersfinal String alias) {
        moveToEnd(ciphers.get(alias));
    }
    static void moveToEnd(final LinkedHashSet<Cipherciphersfinal Collection<CiphertoBeMovedCiphers) {
        List<CiphermovedCiphers = new ArrayList<Cipher>(toBeMovedCiphers);
        movedCiphers.retainAll(ciphers);
        ciphers.removeAll(movedCiphers);
        ciphers.addAll(movedCiphers);
    }
    static void add(final LinkedHashSet<Cipherciphersfinal String alias) {
        ciphers.addAll(.get(alias));
    }
    static void remove(final LinkedHashSet<Cipherciphersfinal String alias) {
        ciphers.removeAll(.get(alias));
    }
    static LinkedHashSet<CipherstrengthSort(final LinkedHashSet<Cipherciphers) {
        /*
         * This routine sorts the ciphers with descending strength. The sorting
         * must keep the pre-sorted sequence, so we apply the normal sorting
         * routine as '+' movement to the end of the list.
         */
        Set<IntegerkeySizes = new HashSet<Integer>();
        for (Cipher cipher : ciphers) {
            keySizes.add(Integer.valueOf(cipher.getStrength_bits()));
        }
        List<Integerstrength_bits = new ArrayList<Integer>(keySizes);
        Collections.sort(strength_bits);
        Collections.reverse(strength_bits);
        final LinkedHashSet<Cipherresult = new LinkedHashSet<Cipher>(ciphers);
        for (int strength : strength_bits) {
            moveToEnd(resultfilterByStrengthBits(ciphersstrength));
        }
        return result;
    }
    static LinkedHashSet<CipherdefaultSort(final LinkedHashSet<Cipherciphers) {
        final LinkedHashSet<Cipherresult = new LinkedHashSet<Cipher>(ciphers.size());
        /* Now arrange all ciphers by preference: */
        /* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */
        result.addAll(filterByKeyExchange(ciphers, Collections.singleton(.)));
        /* AES is our preferred symmetric cipher */
        result.addAll(filterByEncryption(ciphersnew HashSet<Encryption>(Arrays.asList(..,
                ..))));
        /* Temporarily enable everything else for sorting */
        result.addAll(ciphers);
        /* Low priority for SSLv2 */
        moveToEnd(resultfilterByProtocol(result, Collections.singleton(.)));
        /* Low priority for MD5 */
        moveToEnd(resultfilterByMessageDigest(result, Collections.singleton(.)));
        /* Move anonymous ciphers to the end.  Usually, these will remain disabled.
         * (For applications that allow them, they aren't too bad, but we prefer
         * authenticated ciphers.) */
        moveToEnd(resultfilterByAuthentication(result, Collections.singleton(.)));
        /* Move ciphers without forward secrecy to the end */
        moveToEnd(resultfilterByAuthentication(result, Collections.singleton(.)));
        moveToEnd(resultfilterByKeyExchange(result, Collections.singleton(.)));
        moveToEnd(resultfilterByKeyExchange(result, Collections.singleton(.)));
        moveToEnd(resultfilterByKeyExchange(result, Collections.singleton(.)));
        /* RC4 is sort-of broken -- move the the end */
        moveToEnd(resultfilterByEncryption(result, Collections.singleton(.)));
        return strengthSort(result);
    }
    static Set<CipherfilterByStrengthBits(Set<Cipherciphersint strength_bits) {
        Set<Cipherresult = new LinkedHashSet<Cipher>(ciphers.size());
        for (Cipher cipher : ciphers) {
            if (cipher.getStrength_bits() == strength_bits) {
                result.add(cipher);
            }
        }
        return result;
    }
    static Set<CipherfilterByProtocol(Set<CipherciphersSet<Protocolprotocol) {
        return filter(ciphersprotocolnullnullnullnullnull);
    }
    static Set<CipherfilterByKeyExchange(Set<CipherciphersSet<KeyExchangekx) {
        return filter(ciphersnullkxnullnullnullnull);
    }
    static Set<CipherfilterByAuthentication(Set<CipherciphersSet<Authenticationau) {
        return filter(ciphersnullnullaunullnullnull);
    }
    static Set<CipherfilterByEncryption(Set<CipherciphersSet<Encryptionenc) {
        return filter(ciphersnullnullnullencnullnull);
    }
    static Set<CipherfilterByEncryptionLevel(Set<CipherciphersSet<EncryptionLevellevel) {
        return filter(ciphersnullnullnullnulllevelnull);
    }
    static Set<CipherfilterByMessageDigest(Set<CipherciphersSet<MessageDigestmac) {
        return filter(ciphersnullnullnullnullnullmac);
    }
    static Set<Cipherfilter(Set<CipherciphersSet<ProtocolprotocolSet<KeyExchangekx,
            Set<AuthenticationauSet<EncryptionencSet<EncryptionLevellevelSet<MessageDigestmac) {
        Set<Cipherresult = new LinkedHashSet<Cipher>(ciphers.size());
        for (Cipher cipher : ciphers) {
            if (protocol != null && protocol.contains(cipher.getProtocol())) {
                result.add(cipher);
            }
            if (kx != null && kx.contains(cipher.getKx())) {
                result.add(cipher);
            }
            if (au != null && au.contains(cipher.getAu())) {
                result.add(cipher);
            }
            if (enc != null && enc.contains(cipher.getEnc())) {
                result.add(cipher);
            }
            if (level != null && level.contains(cipher.getLevel())) {
                result.add(cipher);
            }
            if (mac != null && mac.contains(cipher.getMac())) {
                result.add(cipher);
            }
        }
        return result;
    }
    static LinkedHashSet<Cipherparse(String expression) {
        if (!) {
            init();
        }
        String[] elements = expression.split();
        LinkedHashSet<Cipherciphers = new LinkedHashSet<Cipher>();
        Set<CipherremovedCiphers = new HashSet<Cipher>();
        for (String element : elements) {
            if (element.startsWith()) {
                String alias = element.substring(1);
                if (.containsKey(alias)) {
                    remove(ciphersalias);
                }
            } else if (element.startsWith()) {
                String alias = element.substring(1);
                if (.containsKey(alias)) {
                    removedCiphers.addAll(.get(alias));
                } else {
                    ..warnUnknowElement(alias);
                }
            } else if (element.startsWith()) {
                String alias = element.substring(1);
                if (.containsKey(alias)) {
                    moveToEnd(ciphersalias);
                }
            } else if ("@STRENGTH".equals(element)) {
                strengthSort(ciphers);
                break;
            } else if (.containsKey(element)) {
                add(cipherselement);
            } else if (element.contains()) {
                String[] intersections = element.split("\\" + );
                if(intersections.length > 0 && .containsKey(intersections[0])) {
                    List<Cipherresult = new ArrayList<Cipher>(.get(intersections[0]));
                    for(int i = 1; i < intersections.lengthi++) {
                        if(.containsKey(intersections[i])) {
                            result.retainAll(.get(intersections[i]));
                        }
                    }
                     ciphers.addAll(result);
                }
            }
        }
        ciphers.removeAll(removedCiphers);
        return defaultSort(ciphers);
    }
    static List<StringconvertForJSSE(Collection<Cipherciphers) {
        List<Stringresult = new ArrayList<String>(ciphers.size());
        for (Cipher cipher : ciphers) {
            result.addAll(cipher.getJsseNames());
        }
        ..logEnabledCiphers(displayResult(cipherstrue","));
        return result;
    }

    
Parse the specified expression according to the OpenSSL syntax and returns a list of standard cipher names.

Parameters:
expression the openssl expression to define a list of cipher.
Returns:
the corresponding list of ciphers.
    public static List<StringparseExpression(String expression) {
        return convertForJSSE(parse(expression));
    }
    static String displayResult(Collection<Cipherciphersboolean useJSSEFormatString separator) {
        if (ciphers.isEmpty()) {
            return "";
        }
        StringBuilder builder = new StringBuilder(ciphers.size() * 16);
        for (Cipher cipher : ciphers) {
            if (useJSSEFormat) {
                for (String name : cipher.getJsseNames()) {
                    builder.append(name);
                    builder.append(separator);
                }
            } else {
                builder.append(cipher.getOpenSSLAlias());
            }
            builder.append(separator);
        }
        return builder.toString().substring(0, builder.length() - 1);
    }
New to GrepCode? Check out our FAQ X