001/*
002 * Copyright 2015-2024 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns.record;
012
013import org.minidns.record.NSEC3.HashAlgorithm;
014import org.minidns.record.Record.TYPE;
015
016import java.io.DataInputStream;
017import java.io.DataOutputStream;
018import java.io.IOException;
019import java.math.BigInteger;
020import java.util.Locale;
021
022/**
023 * NSEC3PARAM record payload.
024 */
025public class NSEC3PARAM extends Data {
026
027    /**
028     * The cryptographic hash algorithm used.
029     * 
030     */
031    public final HashAlgorithm hashAlgorithm;
032
033    /**
034     * The cryptographic hash algorithm used.
035     * 
036     */
037    public final byte hashAlgorithmByte;
038
039    public final byte flags;
040
041    /**
042     * The number of iterations the hash algorithm is applied.
043     */
044    public final int /* unsigned short */ iterations;
045
046    /**
047     * The salt appended to the next owner name before hashing.
048     */
049    private final byte[] salt;
050
051    public static NSEC3PARAM parse(DataInputStream dis) throws IOException {
052        byte hashAlgorithm = dis.readByte();
053        byte flags = dis.readByte();
054        int iterations = dis.readUnsignedShort();
055        int saltLength = dis.readUnsignedByte();
056        byte[] salt = new byte[saltLength];
057        if (dis.read(salt) != salt.length && salt.length != 0) throw new IOException();
058        return new NSEC3PARAM(hashAlgorithm, flags, iterations, salt);
059    }
060
061    private NSEC3PARAM(HashAlgorithm hashAlgorithm, byte hashAlgorithmByte, byte flags, int iterations, byte[] salt) {
062        assert hashAlgorithmByte == (hashAlgorithm != null ? hashAlgorithm.value : hashAlgorithmByte);
063        this.hashAlgorithmByte = hashAlgorithmByte;
064        this.hashAlgorithm = hashAlgorithm != null ? hashAlgorithm : HashAlgorithm.forByte(hashAlgorithmByte);
065
066        this.flags = flags;
067        this.iterations = iterations;
068        this.salt = salt;
069    }
070
071    NSEC3PARAM(byte hashAlgorithm, byte flags, int iterations, byte[] salt) {
072        this(null, hashAlgorithm, flags, iterations, salt);
073    }
074
075    @Override
076    public TYPE getType() {
077        return TYPE.NSEC3PARAM;
078    }
079
080    @Override
081    public void serialize(DataOutputStream dos) throws IOException {
082        dos.writeByte(hashAlgorithmByte);
083        dos.writeByte(flags);
084        dos.writeShort(iterations);
085        dos.writeByte(salt.length);
086        dos.write(salt);
087    }
088
089    @Override
090    public String toString() {
091        StringBuilder sb = new StringBuilder()
092                .append(hashAlgorithm).append(' ')
093                .append(flags).append(' ')
094                .append(iterations).append(' ')
095                .append(salt.length == 0 ? "-" : new BigInteger(1, salt).toString(16).toUpperCase(Locale.ROOT));
096        return sb.toString();
097    }
098
099    public int getSaltLength() {
100        return salt.length;
101    }
102}