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;
020
021/**
022 * NSEC3PARAM record payload.
023 */
024public class NSEC3PARAM extends Data {
025
026    /**
027     * The cryptographic hash algorithm used.
028     * 
029     */
030    public final HashAlgorithm hashAlgorithm;
031
032    /**
033     * The cryptographic hash algorithm used.
034     * 
035     */
036    public final byte hashAlgorithmByte;
037
038    public final byte flags;
039
040    /**
041     * The number of iterations the hash algorithm is applied.
042     */
043    public final int /* unsigned short */ iterations;
044
045    /**
046     * The salt appended to the next owner name before hashing.
047     */
048    private final byte[] salt;
049
050    public static NSEC3PARAM parse(DataInputStream dis) throws IOException {
051        byte hashAlgorithm = dis.readByte();
052        byte flags = dis.readByte();
053        int iterations = dis.readUnsignedShort();
054        int saltLength = dis.readUnsignedByte();
055        byte[] salt = new byte[saltLength];
056        if (dis.read(salt) != salt.length && salt.length != 0) throw new IOException();
057        return new NSEC3PARAM(hashAlgorithm, flags, iterations, salt);
058    }
059
060    private NSEC3PARAM(HashAlgorithm hashAlgorithm, byte hashAlgorithmByte, byte flags, int iterations, byte[] salt) {
061        assert hashAlgorithmByte == (hashAlgorithm != null ? hashAlgorithm.value : hashAlgorithmByte);
062        this.hashAlgorithmByte = hashAlgorithmByte;
063        this.hashAlgorithm = hashAlgorithm != null ? hashAlgorithm : HashAlgorithm.forByte(hashAlgorithmByte);
064
065        this.flags = flags;
066        this.iterations = iterations;
067        this.salt = salt;
068    }
069
070    NSEC3PARAM(byte hashAlgorithm, byte flags, int iterations, byte[] salt) {
071        this(null, hashAlgorithm, flags, iterations, salt);
072    }
073
074    @Override
075    public TYPE getType() {
076        return TYPE.NSEC3PARAM;
077    }
078
079    @Override
080    public void serialize(DataOutputStream dos) throws IOException {
081        dos.writeByte(hashAlgorithmByte);
082        dos.writeByte(flags);
083        dos.writeShort(iterations);
084        dos.writeByte(salt.length);
085        dos.write(salt);
086    }
087
088    @Override
089    public String toString() {
090        StringBuilder sb = new StringBuilder()
091                .append(hashAlgorithm).append(' ')
092                .append(flags).append(' ')
093                .append(iterations).append(' ')
094                .append(salt.length == 0 ? "-" : new BigInteger(1, salt).toString(16).toUpperCase());
095        return sb.toString();
096    }
097
098    public int getSaltLength() {
099        return salt.length;
100    }
101}