Skip to content

Commit

Permalink
Merge branch '22-add-support-for-rfc-9579' into 'main'
Browse files Browse the repository at this point in the history
add support for rfc 9579

Closes #22

See merge request root/bc-java!61
  • Loading branch information
dghgit committed Jan 4, 2025
2 parents 7c9f835 + a370809 commit 29b3da1
Show file tree
Hide file tree
Showing 6 changed files with 582 additions and 6 deletions.
23 changes: 19 additions & 4 deletions pkix/src/main/java/org/bouncycastle/pkcs/MacDataGenerator.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.bouncycastle.pkcs;


import java.io.IOException;

import java.io.OutputStream;

import org.bouncycastle.asn1.pkcs.MacData;
import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.bouncycastle.operator.MacCalculator;
import org.bouncycastle.util.Strings;

class MacDataGenerator
{
Expand Down Expand Up @@ -42,8 +44,21 @@ public MacData build(char[] password, byte[] data)
AlgorithmIdentifier algId = macCalculator.getAlgorithmIdentifier();

DigestInfo dInfo = new DigestInfo(builder.getDigestAlgorithmIdentifier(), macCalculator.getMac());
PKCS12PBEParams params = PKCS12PBEParams.getInstance(algId.getParameters());

return new MacData(dInfo, params.getIV(), params.getIterations().intValue());
byte[] salt;
int iterations;

if (PKCSObjectIdentifiers.id_PBMAC1.equals(dInfo.getAlgorithmId().getAlgorithm()))
{
salt = Strings.toUTF8ByteArray("NOT USED".toCharArray());
iterations = 1;
}
else
{
PKCS12PBEParams params = PKCS12PBEParams.getInstance(algId.getParameters());
salt = params.getIV();
iterations = params.getIterations().intValue();
}

return new MacData(dInfo, salt, iterations);
}
}
19 changes: 17 additions & 2 deletions pkix/src/main/java/org/bouncycastle/pkcs/PKCS12PfxPdu.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.ContentInfo;
import org.bouncycastle.asn1.pkcs.MacData;
import org.bouncycastle.asn1.pkcs.PBMAC1Params;
import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.Pfx;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.util.Arrays;
Expand Down Expand Up @@ -107,8 +109,21 @@ public boolean isMacValid(PKCS12MacCalculatorBuilderProvider macCalcProviderBuil
if (hasMac())
{
MacData pfxmData = pfx.getMacData();
MacDataGenerator mdGen = new MacDataGenerator(macCalcProviderBuilder.get(new AlgorithmIdentifier(pfxmData.getMac().getAlgorithmId().getAlgorithm(), new PKCS12PBEParams(pfxmData.getSalt(), pfxmData.getIterationCount().intValue()))));

MacDataGenerator mdGen;
if (PKCSObjectIdentifiers.id_PBMAC1.equals(pfxmData.getMac().getAlgorithmId().getAlgorithm()))
{
PBMAC1Params pbmac1Params = PBMAC1Params.getInstance(pfxmData.getMac().getAlgorithmId().getParameters());
if (pbmac1Params == null)
{
throw new PKCSException("If the DigestAlgorithmIdentifier is id-PBMAC1, then the parameters field must contain valid PBMAC1-params parameters.");
}
mdGen = new MacDataGenerator(macCalcProviderBuilder.get(new AlgorithmIdentifier(pfxmData.getMac().getAlgorithmId().getAlgorithm(), pbmac1Params)));
}
else
{
mdGen = new MacDataGenerator(macCalcProviderBuilder.get(new AlgorithmIdentifier(pfxmData.getMac().getAlgorithmId().getAlgorithm(), new PKCS12PBEParams(pfxmData.getSalt(), pfxmData.getIterationCount().intValue()))));
}

try
{
MacData mData = mdGen.build(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.bouncycastle.pkcs.bc;

import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PBMAC1Params;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.MacCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS12MacCalculatorBuilder;

import java.io.IOException;

public class BcPKCS12PBMac1CalculatorBuilder
implements PKCS12MacCalculatorBuilder
{
private final PBMAC1Params pbmac1Params;
private PBKDF2Params pbkdf2Params = null;

public BcPKCS12PBMac1CalculatorBuilder(PBMAC1Params pbeMacParams) throws IOException
{
this.pbmac1Params = pbeMacParams;
if (PKCSObjectIdentifiers.id_PBKDF2.equals(pbeMacParams.getKeyDerivationFunc().getAlgorithm()))
{
this.pbkdf2Params = PBKDF2Params.getInstance(pbeMacParams.getKeyDerivationFunc().getParameters());
if (pbkdf2Params.getKeyLength() == null)
{
throw new IOException("Key length must be present when using PBMAC1.");
}
}
// TODO handle other cases
}

@Override
public AlgorithmIdentifier getDigestAlgorithmIdentifier()
{
return new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBMAC1, pbmac1Params);
}

public MacCalculator build(final char[] password) throws OperatorCreationException
{
return PKCS12PBEUtils.createPBMac1Calculator(pbmac1Params, pbkdf2Params, password);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.bouncycastle.pkcs.bc;

import org.bouncycastle.asn1.pkcs.PBMAC1Params;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.operator.MacCalculator;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.pkcs.PKCS12MacCalculatorBuilder;
import org.bouncycastle.pkcs.PKCS12MacCalculatorBuilderProvider;

import java.io.IOException;

public class BcPKCS12PBMac1CalculatorBuilderProvider
implements PKCS12MacCalculatorBuilderProvider
{
public PKCS12MacCalculatorBuilder get(final AlgorithmIdentifier algorithmIdentifier)
{
return new PKCS12MacCalculatorBuilder()
{
public MacCalculator build(final char[] password)
throws OperatorCreationException
{
if (!PKCSObjectIdentifiers.id_PBMAC1.equals(algorithmIdentifier.getAlgorithm()))
{
throw new OperatorCreationException("protection algorithm not PB mac based");
}

BcPKCS12PBMac1CalculatorBuilder bldr;
try
{
bldr = new BcPKCS12PBMac1CalculatorBuilder(PBMAC1Params.getInstance(algorithmIdentifier.getParameters()));
}
catch (IOException e)
{
throw new OperatorCreationException("invalid parameters in protection algorithm: " + e.getMessage());
}
return bldr.build(password);
}

public AlgorithmIdentifier getDigestAlgorithmIdentifier()
{
return new AlgorithmIdentifier(algorithmIdentifier.getAlgorithm(), algorithmIdentifier.getParameters());
}
};
}
}
68 changes: 68 additions & 0 deletions pkix/src/main/java/org/bouncycastle/pkcs/bc/PKCS12PBEUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@
import java.util.Set;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.asn1.pkcs.PBMAC1Params;
import org.bouncycastle.asn1.pkcs.PKCS12PBEParams;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;
import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA512Digest;
import org.bouncycastle.crypto.engines.DESedeEngine;
import org.bouncycastle.crypto.engines.RC2Engine;
import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.io.MacOutputStream;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
Expand All @@ -26,7 +33,9 @@
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.operator.GenericKey;
import org.bouncycastle.operator.MacCalculator;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Integers;
import org.bouncycastle.util.Strings;

class PKCS12PBEUtils
{
Expand Down Expand Up @@ -127,6 +136,65 @@ public GenericKey getKey()
};
}

static MacCalculator createPBMac1Calculator(final PBMAC1Params pbmac1Params, final PBKDF2Params pbkdf2Params, final char[] password)
{
final HMac hMac = new HMac(getPrf(pbmac1Params.getMessageAuthScheme().getAlgorithm()));

PBEParametersGenerator generator = new PKCS5S2ParametersGenerator(getPrf(pbkdf2Params.getPrf().getAlgorithm()));

generator.init(
Strings.toUTF8ByteArray(password),
pbkdf2Params.getSalt(),
BigIntegers.intValueExact(pbkdf2Params.getIterationCount()));

CipherParameters key = generator.generateDerivedParameters(BigIntegers.intValueExact(pbkdf2Params.getKeyLength()) * 8);

hMac.init(key);

return new MacCalculator()
{
public AlgorithmIdentifier getAlgorithmIdentifier()
{
return new AlgorithmIdentifier(PKCSObjectIdentifiers.id_PBMAC1, pbmac1Params);
}

public OutputStream getOutputStream()
{
return new MacOutputStream(hMac);
}

public byte[] getMac()
{
byte[] res = new byte[hMac.getMacSize()];

hMac.doFinal(res, 0);

return res;
}

public GenericKey getKey()
{
return new GenericKey(getAlgorithmIdentifier(), Strings.toUTF8ByteArray(password));
}
};
}

private static Digest getPrf(ASN1ObjectIdentifier prfId)
{
if (PKCSObjectIdentifiers.id_hmacWithSHA256.equals(prfId))
{
return new SHA256Digest();
}
else if (PKCSObjectIdentifiers.id_hmacWithSHA512.equals(prfId))
{
return new SHA512Digest();
}
else
{
throw new IllegalArgumentException("unknown prf id " + prfId);
}
}

static CipherParameters createCipherParameters(ASN1ObjectIdentifier algorithm, ExtendedDigest digest, int blockSize, PKCS12PBEParams pbeParams, char[] password)
{
PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(digest);
Expand Down
Loading

0 comments on commit 29b3da1

Please sign in to comment.