public boolean isValid(PKMACValue value, char[] password, SubjectPublicKeyInfo keyInfo) throws CRMFException { builder.setParameters(PBMParameter.getInstance(value.getAlgId().getParameters())); MacCalculator calculator = builder.build(password); OutputStream macOut = calculator.getOutputStream(); try { macOut.write(keyInfo.getEncoded(ASN1Encoding.DER)); macOut.close(); } catch (IOException e) { throw new CRMFException("exception encoding mac input: " + e.getMessage(), e); } return Arrays.areEqual(calculator.getMac(), value.getValue().getBytes()); }
public MacCalculator build(char[] password) throws CRMFException { if (parameters != null) { return genCalculator(parameters, password); } else { byte[] salt = new byte[saltLength]; if (random == null) { this.random = new SecureRandom(); } random.nextBytes(salt); return genCalculator(new PBMParameter(salt, owf, iterationCount, mac), password); } }
public PKMACBuilder setParameters(PBMParameter parameters) { checkIterationCountCeiling(parameters.getIterationCount().getValue().intValue()); this.parameters = parameters; return this; }
/** * Verify a message with password based MAC protection. * * @param pkMacBuilder MAC builder that can be used to construct the appropriate MacCalculator * @param password the MAC password * @return true if the passed in password and MAC builder verify the message, false otherwise. * @throws CMPException if algorithm not MAC based, or an exception is thrown verifying the MAC. */ public boolean verify(PKMACBuilder pkMacBuilder, char[] password) throws CMPException { if (!CMPObjectIdentifiers.passwordBasedMac.equals(pkiMessage.getHeader().getProtectionAlg().getAlgorithm())) { throw new CMPException("protection algorithm not mac based"); } try { pkMacBuilder.setParameters(PBMParameter.getInstance(pkiMessage.getHeader().getProtectionAlg().getParameters())); MacCalculator calculator = pkMacBuilder.build(password); OutputStream macOut = calculator.getOutputStream(); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(pkiMessage.getHeader()); v.add(pkiMessage.getBody()); macOut.write(new DERSequence(v).getEncoded(ASN1Encoding.DER)); macOut.close(); return Arrays.areEqual(calculator.getMac(), pkiMessage.getProtection().getBytes()); } catch (Exception e) { throw new CMPException("unable to verify MAC: " + e.getMessage(), e); } }
/** * Creates a new PKMACValue. * @param params parameters for password-based MAC * @param value MAC of the DER-encoded SubjectPublicKeyInfo */ public PKMACValue( PBMParameter params, DERBitString value) { this(new AlgorithmIdentifier( CMPObjectIdentifiers.passwordBasedMac, params), value); }
private MacCalculator genCalculator(final PBMParameter params, char[] password) throws CRMFException { // From RFC 4211 // // 1. Generate a random salt value S // // 2. Append the salt to the pw. K = pw || salt. // // 3. Hash the value of K. K = HASH(K) // // 4. Iter = Iter - 1. If Iter is greater than zero. Goto step 3. // // 5. Compute an HMAC as documented in [HMAC]. // // MAC = HASH( K XOR opad, HASH( K XOR ipad, data) ) // // Where opad and ipad are defined in [HMAC]. byte[] pw = Strings.toUTF8ByteArray(password); byte[] salt = params.getSalt().getOctets(); byte[] K = new byte[pw.length + salt.length]; System.arraycopy(pw, 0, K, 0, pw.length); System.arraycopy(salt, 0, K, pw.length, salt.length); calculator.setup(params.getOwf(), params.getMac()); int iter = params.getIterationCount().getValue().intValue(); do { K = calculator.calculateDigest(K); } while (--iter > 0); final byte[] key = K; return new MacCalculator() { ByteArrayOutputStream bOut = new ByteArrayOutputStream(); public AlgorithmIdentifier getAlgorithmIdentifier() { return new AlgorithmIdentifier(CMPObjectIdentifiers.passwordBasedMac, params); } public GenericKey getKey() { return new GenericKey(getAlgorithmIdentifier(), key); } public OutputStream getOutputStream() { return bOut; } public byte[] getMac() { try { return calculator.calculateMac(key, bOut.toByteArray()); } catch (CRMFException e) { throw new RuntimeOperatorException("exception calculating mac: " + e.getMessage(), e); } } }; }