Skip to content

Commit aab36ef

Browse files
committed
Add PBMAC1 ASN.1 structures and configuration API. Claude sonnet 4.5 assisted.
1 parent ab95759 commit aab36ef

3 files changed

Lines changed: 247 additions & 0 deletions

File tree

base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12Util.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@
6262
import org.mozilla.jss.pkcs12.AuthenticatedSafes;
6363
import org.mozilla.jss.pkcs12.CertBag;
6464
import org.mozilla.jss.pkcs12.PFX;
65+
import org.mozilla.jss.pkcs12.MacType;
6566
import org.mozilla.jss.pkcs12.PasswordConverter;
6667
import org.mozilla.jss.pkcs12.SafeBag;
6768
import org.mozilla.jss.pkix.primitive.Attribute;
6869
import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
6970
import org.mozilla.jss.util.Password;
71+
import org.mozilla.jss.crypto.DigestAlgorithm;
7072
import org.slf4j.Logger;
7173
import org.slf4j.LoggerFactory;
7274

@@ -97,6 +99,49 @@ public class PKCS12Util {
9799
PBEAlgorithm keyEncryption = DEFAULT_KEY_ENCRYPTION;
98100
boolean trustFlagsEnabled = true;
99101

102+
// MAC configuration (separate from encryption)
103+
private MacType macType = MacType.CLASSIC; // default for backward compatibility
104+
private DigestAlgorithm macDigest = DigestAlgorithm.SHA256; // default digest
105+
106+
/**
107+
* Sets the MAC algorithm type for PKCS#12 file generation.
108+
*
109+
* @param type The MAC type (CLASSIC or PBMAC1)
110+
* @throws IllegalArgumentException
111+
*/
112+
public void setMacType(MacType type) {
113+
if(type == null) {
114+
throw new IllegalArgumentException("Must provide macType");
115+
}
116+
this.macType = type;
117+
}
118+
119+
/**
120+
* Returns the configured MAC algorithm type.
121+
*
122+
* @return The MAC type
123+
*/
124+
public MacType getMacType() {
125+
return macType;
126+
}
127+
128+
/**
129+
* Sets the configured MAC digest algorithm.
130+
*
131+
* @param digest The digest algorithm
132+
* @throws IllegalArgumentException
133+
*/
134+
public void setMacDigest(DigestAlgorithm digest) {
135+
if(digest == null) {
136+
throw new IllegalArgumentException("Must provide digest");
137+
}
138+
this.macDigest = digest;
139+
}
140+
141+
public DigestAlgorithm getMacDigest() {
142+
return macDigest;
143+
}
144+
100145
public PKCS12Util() throws Exception {
101146
random = SecureRandom.getInstance("pkcs11prng", "Mozilla-JSS");
102147
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
package org.mozilla.jss.pkcs12;
6+
7+
/**
8+
* Defines the MAC algorithm type for PKCS#12 integrity protection.
9+
*/
10+
public enum MacType {
11+
CLASSIC,
12+
PBMAC1
13+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
package org.mozilla.jss.pkix.primitive;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.io.OutputStream;
10+
11+
import org.mozilla.jss.asn1.ASN1Template;
12+
import org.mozilla.jss.asn1.ASN1Value;
13+
import org.mozilla.jss.asn1.InvalidBERException;
14+
import org.mozilla.jss.asn1.SEQUENCE;
15+
import org.mozilla.jss.asn1.Tag;
16+
17+
/**
18+
* PKCS #5 <i>PBMAC1-params</i> from RFC 9579.
19+
*
20+
* <pre>
21+
* PBMAC1-params ::= SEQUENCE {
22+
* keyDerivationFunc AlgorithmIdentifier {{PBMAC1-KDFs}},
23+
* messageAuthScheme AlgorithmIdentifier {{PBMAC1-MACs}}
24+
* }
25+
* </pre>
26+
*/
27+
public class PBMAC1Params implements ASN1Value {
28+
29+
///////////////////////////////////////////////////////////////////////
30+
// members and member access
31+
///////////////////////////////////////////////////////////////////////
32+
private AlgorithmIdentifier keyDerivationFunc;
33+
private AlgorithmIdentifier messageAuthScheme;
34+
private SEQUENCE sequence;
35+
36+
/**
37+
* Returns the key derivation function (typically PBKDF2).
38+
*/
39+
public AlgorithmIdentifier getKeyDerivationFunc() {
40+
return keyDerivationFunc;
41+
}
42+
43+
/**
44+
* Returns the message authentication scheme (typically HMAC-SHA256/384/512).
45+
*/
46+
public AlgorithmIdentifier getMessageAuthScheme() {
47+
return messageAuthScheme;
48+
}
49+
50+
///////////////////////////////////////////////////////////////////////
51+
// constructors
52+
///////////////////////////////////////////////////////////////////////
53+
54+
/**
55+
* Creates PBMAC1 parameters.
56+
*
57+
* @param keyDerivationFunc The key derivation function AlgorithmIdentifier
58+
* (typically PBKDF2 with salt, iterations, and PRF)
59+
* @param messageAuthScheme The MAC algorithm AlgorithmIdentifier
60+
* (typically HMAC-SHA256, HMAC-SHA384, or HMAC-SHA512)
61+
*/
62+
public PBMAC1Params(AlgorithmIdentifier keyDerivationFunc,
63+
AlgorithmIdentifier messageAuthScheme) {
64+
65+
if (keyDerivationFunc == null || messageAuthScheme == null) {
66+
throw new IllegalArgumentException("Parameters cannot be null");
67+
}
68+
69+
this.keyDerivationFunc = keyDerivationFunc;
70+
this.messageAuthScheme = messageAuthScheme;
71+
sequence = new SEQUENCE();
72+
sequence.addElement(keyDerivationFunc);
73+
sequence.addElement(messageAuthScheme);
74+
}
75+
76+
///////////////////////////////////////////////////////////////////////
77+
// DER encoding
78+
///////////////////////////////////////////////////////////////////////
79+
80+
private static final Tag TAG = SEQUENCE.TAG;
81+
82+
/**
83+
* Returns the ASN.1 tag for this structure.
84+
*
85+
* @return The SEQUENCE tag
86+
*/
87+
@Override
88+
public Tag getTag() {
89+
return TAG;
90+
}
91+
92+
/**
93+
* Encodes this PBMAC1Params to the output stream.
94+
*
95+
* @param ostream The output stream
96+
* @throws IOException if encoding fails
97+
*/
98+
@Override
99+
public void encode(OutputStream ostream) throws IOException {
100+
sequence.encode(ostream);
101+
}
102+
103+
/**
104+
* Encodes this PBMAC1Params with an implicit tag.
105+
*
106+
* @param implicitTag The implicit tag to use
107+
* @param ostream The output stream
108+
* @throws IOException if encoding fails
109+
*/
110+
@Override
111+
public void encode(Tag implicitTag, OutputStream ostream)
112+
throws IOException
113+
{
114+
sequence.encode(implicitTag, ostream);
115+
}
116+
117+
private static final Template templateInstance = new Template();
118+
119+
/**
120+
* Returns the template for decoding PBMAC1Params.
121+
*
122+
* @return The PBMAC1Params template
123+
*/
124+
public static Template getTemplate() {
125+
return templateInstance;
126+
}
127+
128+
/**
129+
* A template class for decoding PBMAC1Params.
130+
*/
131+
public static class Template implements ASN1Template {
132+
133+
private SEQUENCE.Template seqt;
134+
135+
/**
136+
* Creates a new PBMAC1Params template.
137+
*/
138+
public Template() {
139+
seqt = new SEQUENCE.Template();
140+
seqt.addElement(AlgorithmIdentifier.getTemplate());
141+
seqt.addElement(AlgorithmIdentifier.getTemplate());
142+
}
143+
144+
/**
145+
* Returns whether the given tag matches this template.
146+
*
147+
* @param tag The tag to check
148+
* @return true if the tag matches
149+
*/
150+
@Override
151+
public boolean tagMatch(Tag tag) {
152+
return TAG.equals(tag);
153+
}
154+
155+
/**
156+
* Decodes a PBMAC1Params from the input stream.
157+
*
158+
* @param istream The input stream
159+
* @return The decoded PBMAC1Params
160+
* @throws InvalidBERException if decoding fails
161+
* @throws IOException if an I/O error occurs
162+
*/
163+
@Override
164+
public ASN1Value decode(InputStream istream)
165+
throws InvalidBERException, IOException
166+
{
167+
return decode(TAG, istream);
168+
}
169+
170+
/**
171+
* Decodes a PBMAC1Params with an implicit tag.
172+
*
173+
* @param implicitTag The implicit tag
174+
* @param istream The input stream
175+
* @return The decoded PBMAC1Params
176+
* @throws InvalidBERException if decoding fails
177+
* @throws IOException if an I/O error occurs
178+
*/
179+
@Override
180+
public ASN1Value decode(Tag implicitTag, InputStream istream)
181+
throws InvalidBERException, IOException
182+
{
183+
SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream);
184+
185+
return new PBMAC1Params((AlgorithmIdentifier) seq.elementAt(0),
186+
(AlgorithmIdentifier) seq.elementAt(1));
187+
}
188+
}
189+
}

0 commit comments

Comments
 (0)