以哪种形式在文档末尾添加文档的散列
In which form add hash of document at the end of document
我使用以下方法获取字节数组:
byte[] digitalSignature = signature.sign();
那么,将其保存在 txt 文件或任何文件类型末尾的最佳方法是什么,以便我在验证签名时可以读取它。我的想法是制作 String
: "Digital signature:" 并以 String
形式添加到这个字节数组中 我试过这个:
String stringAddOnEndOfDocument = new String("Digital signature:" + new String(digitalSignature));
当我读取文件时,我找到“数字签名:”,然后读取 String
并使用 getBytes()
方法转换为字节数组,然后从文件中删除它..但是我无法用这个验证文档的签名..我想从字节到字符串的转换有问题,但我不知道到底是什么..
这是我验证签名的代码:
deleteHashDataFromEndOfFile(testFile);
byte[] messageBytes = Files.readAllBytes(Paths.get(testFile.toString()));
signature.update(messageBytes);
signature.verify(byteArray)
最好的方法是使用单独的文件,但如果您确实必须将签名存储在文件末尾,则有几种方法可以做到这一点。
请记住,new String(digitalSignature)
可能会跳过不可打印的字节,因此会破坏您的签名。您需要始终将其处理为 byte[]
或使用 Hex 或 Base64 编码将其编码为可打印格式。
使用“数字签名:”作为签名后面的标记可能有效,但如果实际文本文件恰好包含此文本,则会中断。要解决这个问题,您可以在整个文件中搜索该文本并只获取最后一次出现的内容,或者您可以以二进制方式进行搜索并将签名始终存储在末尾。由于签名通常总是具有相同的长度,因此它通过仅从文件中切片或复制最后已知的字节来工作。如果签名有可能具有可变长度,您可以将最后 4 个字节指定为签名的长度,并确保签名恰好在此之前。
可以用int lengthOfSignature = new BigInteger(theLast4Bytes).intValue()
读取值,用BigInteger.valueOf(lengthOfSignature).toByteArray()
写入(确保长度为4字节,必要时在前面填充0x00字节)。在读取签名长度时,您的代码应该测试该数字是否有意义:是否为正并且在您期望的范围内,例如 255-257 字节。之后只需要一点点索引数学就可以得到签名。
写作可能是这样的:
byte[] messageBytes = Files.readAllBytes(file);
byte[] signature = sign(privateKey, messageBytes);
byte[] signatureLength = BigInteger.valueOf(lengthOfSignature).toByteArray();
byte[] messageOutput = new byte[messageBytes.length + signature.length + 4];
System.arraycopy(messageBytes, 0, messageOutput, 0, messageBytes.length);
System.arraycopy(signature, 0, messageOutput, messageBytes.length, signature.length);
System.arraycopy(signatureLength, 0, messageOutput, messageBytes.length + signature.length + 4 - signatureLength.length, signatureLength.length); // padding included
// TODO write messageOutput to file
读取和验证签名如下所示:
byte[] msgAndSigBytes = Files.readAllBytes(file);
byte[] signatureLengthBytes = Arrays.copyOfRange(msgAndSigBytes, msgAndSigBytes.length-4, msgAndSigBytes);
int signatureLength = new BigInteger(signatureLengthBytes).intValue();
// TODO check for proper size according to your signature algorithm
byte[] signature = Arrays.copyOfRange(msgAndSigBytes, msgAndSigBytes.length-4-signatureLength, msgAndSigBytes-4);
byte[] msgBytes = Arrays.copyOf(msgAndSigBytes, msgAndSigBytes.length-4-signatureLength);
boolean success = verify(publicKey, signature);
如果文件很大,则应使用流。写入时,可以使用正常的输入或输出流,但读取时要么需要可查找的流,要么需要多次传递。
我使用以下方法获取字节数组:
byte[] digitalSignature = signature.sign();
那么,将其保存在 txt 文件或任何文件类型末尾的最佳方法是什么,以便我在验证签名时可以读取它。我的想法是制作 String
: "Digital signature:" 并以 String
形式添加到这个字节数组中 我试过这个:
String stringAddOnEndOfDocument = new String("Digital signature:" + new String(digitalSignature));
当我读取文件时,我找到“数字签名:”,然后读取 String
并使用 getBytes()
方法转换为字节数组,然后从文件中删除它..但是我无法用这个验证文档的签名..我想从字节到字符串的转换有问题,但我不知道到底是什么..
这是我验证签名的代码:
deleteHashDataFromEndOfFile(testFile);
byte[] messageBytes = Files.readAllBytes(Paths.get(testFile.toString()));
signature.update(messageBytes);
signature.verify(byteArray)
最好的方法是使用单独的文件,但如果您确实必须将签名存储在文件末尾,则有几种方法可以做到这一点。
请记住,new String(digitalSignature)
可能会跳过不可打印的字节,因此会破坏您的签名。您需要始终将其处理为 byte[]
或使用 Hex 或 Base64 编码将其编码为可打印格式。
使用“数字签名:”作为签名后面的标记可能有效,但如果实际文本文件恰好包含此文本,则会中断。要解决这个问题,您可以在整个文件中搜索该文本并只获取最后一次出现的内容,或者您可以以二进制方式进行搜索并将签名始终存储在末尾。由于签名通常总是具有相同的长度,因此它通过仅从文件中切片或复制最后已知的字节来工作。如果签名有可能具有可变长度,您可以将最后 4 个字节指定为签名的长度,并确保签名恰好在此之前。
可以用int lengthOfSignature = new BigInteger(theLast4Bytes).intValue()
读取值,用BigInteger.valueOf(lengthOfSignature).toByteArray()
写入(确保长度为4字节,必要时在前面填充0x00字节)。在读取签名长度时,您的代码应该测试该数字是否有意义:是否为正并且在您期望的范围内,例如 255-257 字节。之后只需要一点点索引数学就可以得到签名。
写作可能是这样的:
byte[] messageBytes = Files.readAllBytes(file);
byte[] signature = sign(privateKey, messageBytes);
byte[] signatureLength = BigInteger.valueOf(lengthOfSignature).toByteArray();
byte[] messageOutput = new byte[messageBytes.length + signature.length + 4];
System.arraycopy(messageBytes, 0, messageOutput, 0, messageBytes.length);
System.arraycopy(signature, 0, messageOutput, messageBytes.length, signature.length);
System.arraycopy(signatureLength, 0, messageOutput, messageBytes.length + signature.length + 4 - signatureLength.length, signatureLength.length); // padding included
// TODO write messageOutput to file
读取和验证签名如下所示:
byte[] msgAndSigBytes = Files.readAllBytes(file);
byte[] signatureLengthBytes = Arrays.copyOfRange(msgAndSigBytes, msgAndSigBytes.length-4, msgAndSigBytes);
int signatureLength = new BigInteger(signatureLengthBytes).intValue();
// TODO check for proper size according to your signature algorithm
byte[] signature = Arrays.copyOfRange(msgAndSigBytes, msgAndSigBytes.length-4-signatureLength, msgAndSigBytes-4);
byte[] msgBytes = Arrays.copyOf(msgAndSigBytes, msgAndSigBytes.length-4-signatureLength);
boolean success = verify(publicKey, signature);
如果文件很大,则应使用流。写入时,可以使用正常的输入或输出流,但读取时要么需要可查找的流,要么需要多次传递。