• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jreleaser / jreleaser / #477

04 Apr 2025 05:53PM UTC coverage: 35.124% (-5.1%) from 40.183%
#477

push

github

aalmiray
fix(deploy): Add missing Forgejo messages

Related to #1842

18210 of 51845 relevant lines covered (35.12%)

0.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/api/jreleaser-model-api/src/main/java/org/jreleaser/model/api/signing/Keyring.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 *
4
 * Copyright 2020-2025 The JReleaser authors.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     https://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
package org.jreleaser.model.api.signing;
19

20
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
21
import org.bouncycastle.openpgp.PGPException;
22
import org.bouncycastle.openpgp.PGPPublicKey;
23
import org.bouncycastle.openpgp.PGPPublicKeyRing;
24
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
25
import org.bouncycastle.openpgp.PGPSecretKey;
26
import org.bouncycastle.openpgp.PGPSecretKeyRing;
27
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
28
import org.bouncycastle.openpgp.operator.KeyFingerPrintCalculator;
29
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator;
30
import org.jreleaser.bundle.RB;
31

32
import java.io.ByteArrayInputStream;
33
import java.io.IOException;
34
import java.io.InputStream;
35
import java.util.Collections;
36
import java.util.Iterator;
37

38
/**
39
 * Adapted from {@code name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.InMemoryKeyring}
40
 * Original author: Jens Neuhalfen
41
 *
42
 * @author Andres Almiray
43
 * @since 0.4.0
44
 */
45
public abstract class Keyring {
46
    private final KeyFingerPrintCalculator keyFingerPrintCalculator = new BcKeyFingerprintCalculator();
×
47
    private PGPPublicKeyRingCollection publicKeyRings;
48
    private PGPSecretKeyRingCollection secretKeyRings;
49

50
    protected Keyring() throws IOException, PGPException {
×
51
        this.publicKeyRings = new PGPPublicKeyRingCollection(Collections.emptyList());
×
52
        this.secretKeyRings = new PGPSecretKeyRingCollection(Collections.emptyList());
×
53
    }
×
54

55
    public Keyring initialize(boolean armored) throws IOException, PGPException {
56
        try (InputStream pub = getPublicKeyRingStream();
×
57
             InputStream sec = getSecretKeyRingStream()) {
×
58
            if (!(pub instanceof EmptyInputStream)) {
×
59
                addPublicKey(armored, pub);
×
60
            }
61
            addSecretKey(armored, sec);
×
62
        }
63

64
        return this;
×
65
    }
66

67
    public KeyFingerPrintCalculator getKeyFingerPrintCalculator() {
68
        return keyFingerPrintCalculator;
×
69
    }
70

71
    protected abstract InputStream getPublicKeyRingStream() throws IOException;
72

73
    protected abstract InputStream getSecretKeyRingStream() throws IOException;
74

75
    public void addPublicKey(boolean armored, InputStream raw) throws IOException {
76
        if (!armored) {
×
77
            addPublicKeyRing(new PGPPublicKeyRing(raw, keyFingerPrintCalculator));
×
78
            return;
×
79
        }
80

81
        try (InputStream decoded = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(raw)) {
×
82
            addPublicKeyRing(new PGPPublicKeyRing(decoded, keyFingerPrintCalculator));
×
83
        }
84
    }
×
85

86
    public void addSecretKey(boolean armored, InputStream raw) throws IOException, PGPException {
87
        if (!armored) {
×
88
            addSecretKeyRing(new PGPSecretKeyRing(raw, keyFingerPrintCalculator));
×
89
            return;
×
90
        }
91

92
        try (InputStream decoded = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(raw)) {
×
93
            addSecretKeyRing(new PGPSecretKeyRing(decoded, keyFingerPrintCalculator));
×
94
        }
95
    }
×
96

97
    public void addSecretKeyRing(PGPSecretKeyRing keyring) {
98
        this.secretKeyRings = PGPSecretKeyRingCollection.addSecretKeyRing(this.secretKeyRings, keyring);
×
99
    }
×
100

101
    public void addPublicKeyRing(PGPPublicKeyRing keyring) {
102
        this.publicKeyRings = PGPPublicKeyRingCollection.addPublicKeyRing(this.publicKeyRings, keyring);
×
103
    }
×
104

105
    public PGPPublicKey readPublicKey() throws SigningException {
106
        Iterator<PGPPublicKeyRing> keyRingIter = publicKeyRings.getKeyRings();
×
107
        while (keyRingIter.hasNext()) {
×
108
            PGPPublicKeyRing keyRing = keyRingIter.next();
×
109

110
            Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys();
×
111
            while (keyIter.hasNext()) {
×
112
                PGPPublicKey key = keyIter.next();
×
113
                if (isSigningKey(key)) {
×
114
                    return key;
×
115
                }
116
            }
×
117
        }
×
118

119
        throw new SigningException(RB.$("ERROR_public_key_not_found"));
×
120
    }
121

122
    public PGPSecretKey readSecretKey() throws SigningException {
123
        Iterator<PGPSecretKeyRing> keyRingIter = secretKeyRings.getKeyRings();
×
124
        while (keyRingIter.hasNext()) {
×
125
            PGPSecretKeyRing keyRing = keyRingIter.next();
×
126

127
            Iterator<PGPSecretKey> keyIter = keyRing.getSecretKeys();
×
128
            while (keyIter.hasNext()) {
×
129
                PGPSecretKey key = keyIter.next();
×
130
                if (key.isSigningKey()) {
×
131
                    return key;
×
132
                }
133
            }
×
134
        }
×
135

136
        throw new SigningException(RB.$("ERROR_secret_key_not_found"));
×
137
    }
138

139
    /**
140
     * Returns {@code true} if the given key can be used for signing.
141
     *
142
     * <p>There is no Method key.isSigningKey(), and encryption does not always mean signing.
143
     * The algorithms here need to be kept in sync with {@code org.bouncycastle.openpgp.operator.jcajce.OperatorHelper#createSignature}.
144
     *
145
     * @param key they key to check if it is usable for signing.
146
     * @return {@code true} if the given key can be used for signing.
147
     */
148
    private static boolean isSigningKey(PGPPublicKey key) {
149
        final int algorithm = key.getAlgorithm();
×
150

151
        return algorithm == PublicKeyAlgorithmTags.EDDSA ||
×
152
            algorithm == PublicKeyAlgorithmTags.ECDSA ||
153
            algorithm == PublicKeyAlgorithmTags.ELGAMAL_GENERAL ||
154
            algorithm == PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT ||
155
            algorithm == PublicKeyAlgorithmTags.RSA_SIGN ||
156
            algorithm == PublicKeyAlgorithmTags.RSA_GENERAL ||
157
            algorithm == PublicKeyAlgorithmTags.DSA;
158
    }
159

160
    public static class EmptyInputStream extends ByteArrayInputStream {
161
        public EmptyInputStream() {
162
            super(new byte[0]);
×
163
        }
×
164
    }
165
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc