public Collection extractKeyPairs()

in sshd-common/src/main/java/org/apache/sshd/common/config/keys/loader/pem/AbstractPEMResourceKeyPairParser.java [78:171]


    public Collection<KeyPair> extractKeyPairs(
            SessionContext session, NamedResource resourceKey,
            String beginMarker, String endMarker,
            FilePasswordProvider passwordProvider,
            List<String> lines, Map<String, String> headers)
            throws IOException, GeneralSecurityException {
        if (GenericUtils.isEmpty(lines)) {
            return Collections.emptyList();
        }

        Boolean encrypted = null;
        byte[] initVector = null;
        String algInfo = null;
        int dataStartIndex = -1;
        boolean hdrsAvailable = MapEntryUtils.isNotEmpty(headers);
        for (int index = 0; index < lines.size(); index++) {
            String line = GenericUtils.trimToEmpty(lines.get(index));
            if (GenericUtils.isEmpty(line)) {
                continue;
            }

            // check if header line - if not, assume data lines follow
            int headerPos = line.indexOf(':');
            if (headerPos < 0) {
                dataStartIndex = index;
                break;
            }

            String hdrName = line.substring(0, headerPos).trim();
            String hdrValue = line.substring(headerPos + 1).trim();
            if (!hdrsAvailable) {
                Map<String, String> accHeaders = MapEntryUtils.isEmpty(headers)
                        ? new TreeMap<>(String.CASE_INSENSITIVE_ORDER)
                        : headers;
                accHeaders.put(hdrName, hdrValue);
            }

            if (hdrName.equalsIgnoreCase("Proc-Type")) {
                if (encrypted != null) {
                    throw new StreamCorruptedException("Multiple encryption indicators in " + resourceKey);
                }

                hdrValue = hdrValue.toUpperCase();
                encrypted = Boolean.valueOf(line.contains("ENCRYPTED"));
            } else if (hdrName.equalsIgnoreCase("DEK-Info")) {
                if ((initVector != null) || (algInfo != null)) {
                    throw new StreamCorruptedException("Multiple encryption settings in " + resourceKey);
                }

                int infoPos = hdrValue.indexOf(',');
                if (infoPos < 0) {
                    throw new StreamCorruptedException(
                            resourceKey + ": Missing encryption data values separator in line '" + line + "'");
                }

                algInfo = hdrValue.substring(0, infoPos).trim();

                String algInitVector = hdrValue.substring(infoPos + 1).trim();
                initVector = BufferUtils.decodeHex(BufferUtils.EMPTY_HEX_SEPARATOR, algInitVector);
            }
        }

        if (dataStartIndex < 0) {
            throw new StreamCorruptedException("No data lines (only headers or empty) found in " + resourceKey);
        }

        List<String> dataLines = lines.subList(dataStartIndex, lines.size());
        if ((encrypted != null) || (algInfo != null) || (initVector != null)) {
            if (passwordProvider == null) {
                throw new CredentialException("Missing password provider for encrypted resource=" + resourceKey);
            }

            byte[] encryptedData = KeyPairResourceParser.extractDataBytes(dataLines);
            String algorithm = algInfo;
            byte[] iv = initVector;
            Collection<KeyPair> keys = passwordProvider.decode(session, resourceKey, password -> {
                PrivateKeyEncryptionContext encContext = new PrivateKeyEncryptionContext(algorithm);
                encContext.setPassword(password);
                encContext.setInitVector(iv);
                byte[] decodedData = GenericUtils.EMPTY_BYTE_ARRAY;
                try {
                    decodedData = applyPrivateKeyCipher(encryptedData, encContext, false);
                    try (InputStream bais = new ByteArrayInputStream(decodedData)) {
                        return extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, bais, headers);
                    }
                } finally {
                    Arrays.fill(decodedData, (byte) 0);
                }
            });
            return keys == null ? Collections.emptyList() : keys;
        }

        return super.extractKeyPairs(session, resourceKey, beginMarker, endMarker, passwordProvider, dataLines, headers);
    }