翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
ステップ 7: 台帳内のドキュメントを検証する
重要
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了QLDBまで Amazon を使用できます。詳細については、「Amazon Ledger QLDB を Amazon Aurora Postgre に移行するSQL
Amazon ではQLDB、SHA-256 で暗号化ハッシュを使用することで、台帳のジャーナル内のドキュメントの整合性を効率的に検証できます。での検証と暗号化ハッシュの仕組みの詳細についてはQLDB、「」を参照してくださいAmazon でのデータ検証 QLDB。
このステップでは、vehicle-registration
台帳の VehicleRegistration
テーブルのドキュメントリビジョンを確認します。まず、ダイジェストをリクエストします。ダイジェストは出力ファイルとして返され、台帳の変更履歴全体の署名として機能します。次に、そのダイジェストに関連するリビジョンの証明をリクエストします。この証明を使用して、すべての検証チェックに合格すると、リビジョンの整合性が検証されます。
ドキュメントのリビジョンを検証するには
-
Ion 値と文字列値のヘルパーメソッドを使用して、検証クラスとユーティリティクラスに必要なQLDBオブジェクトを表す次の
.java
ファイルを確認します。-
BlockAddress.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** * Represents the BlockAddress field of a QLDB document. */ public final class BlockAddress { private static final Logger log = LoggerFactory.getLogger(BlockAddress.class); private final String strandId; private final long sequenceNo; @JsonCreator public BlockAddress(@JsonProperty("strandId") final String strandId, @JsonProperty("sequenceNo") final long sequenceNo) { this.strandId = strandId; this.sequenceNo = sequenceNo; } public long getSequenceNo() { return sequenceNo; } public String getStrandId() { return strandId; } @Override public String toString() { return "BlockAddress{" + "strandId='" + strandId + '\'' + ", sequenceNo=" + sequenceNo + '}'; } @Override public boolean equals(final Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } BlockAddress that = (BlockAddress) o; return sequenceNo == that.sequenceNo && strandId.equals(that.strandId); } @Override public int hashCode() { // CHECKSTYLE:OFF - Disabling as we are generating a hashCode of multiple properties. return Objects.hash(strandId, sequenceNo); // CHECKSTYLE:ON } }
-
Proof.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.amazon.ion.IonReader; import com.amazon.ion.IonSystem; import com.amazon.ion.system.IonSystemBuilder; import com.amazonaws.services.qldb.model.GetRevisionRequest; import com.amazonaws.services.qldb.model.GetRevisionResult; import java.util.ArrayList; import java.util.List; /** * A Java representation of the {@link Proof} object. * Returned from the {@link com.amazonaws.services.qldb.AmazonQLDB#getRevision(GetRevisionRequest)} api. */ public final class Proof { private static final IonSystem SYSTEM = IonSystemBuilder.standard().build(); private List<byte[]> internalHashes; public Proof(final List<byte[]> internalHashes) { this.internalHashes = internalHashes; } public List<byte[]> getInternalHashes() { return internalHashes; } /** * Decodes a {@link Proof} from an ion text String. This ion text is returned in * a {@link GetRevisionResult#getProof()} * * @param ionText * The ion text representing a {@link Proof} object. * @return {@link JournalBlock} parsed from the ion text. * @throws IllegalStateException if failed to parse the {@link Proof} object from the given ion text. */ public static Proof fromBlob(final String ionText) { try { IonReader reader = SYSTEM.newReader(ionText); List<byte[]> list = new ArrayList<>(); reader.next(); reader.stepIn(); while (reader.next() != null) { list.add(reader.newBytes()); } return new Proof(list); } catch (Exception e) { throw new IllegalStateException("Failed to parse a Proof from byte array"); } } }
-
QldbIonUtils.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.amazon.ion.IonReader; import com.amazon.ion.IonValue; import com.amazon.ionhash.IonHashReader; import com.amazon.ionhash.IonHashReaderBuilder; import com.amazon.ionhash.MessageDigestIonHasherProvider; import software.amazon.qldb.tutorial.Constants; public class QldbIonUtils { private static MessageDigestIonHasherProvider ionHasherProvider = new MessageDigestIonHasherProvider("SHA-256"); private QldbIonUtils() {} /** * Builds a hash value from the given {@link IonValue}. * * @param ionValue * The {@link IonValue} to hash. * @return a byte array representing the hash value. */ public static byte[] hashIonValue(final IonValue ionValue) { IonReader reader = Constants.SYSTEM.newReader(ionValue); IonHashReader hashReader = IonHashReaderBuilder.standard() .withHasherProvider(ionHasherProvider) .withReader(reader) .build(); while (hashReader.next() != null) { } return hashReader.digest(); } }
-
QldbStringUtils.java
/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial.qldb; import com.amazon.ion.IonWriter; import com.amazon.ion.system.IonReaderBuilder; import com.amazon.ion.system.IonTextWriterBuilder; import com.amazonaws.services.qldb.model.GetBlockResult; import com.amazonaws.services.qldb.model.GetDigestResult; import com.amazonaws.services.qldb.model.ValueHolder; import java.io.IOException; /** * Helper methods to pretty-print certain QLDB response types. */ public class QldbStringUtils { private QldbStringUtils() {} /** * Returns the string representation of a given {@link ValueHolder}. * Adapted from the AWS SDK autogenerated {@code toString()} method, with sensitive values un-redacted. * Additionally, this method pretty-prints any IonText included in the {@link ValueHolder}. * * @param valueHolder the {@link ValueHolder} to convert to a String. * @return the String representation of the supplied {@link ValueHolder}. */ public static String toUnredactedString(ValueHolder valueHolder) { StringBuilder sb = new StringBuilder(); sb.append("{"); if (valueHolder.getIonText() != null) { sb.append("IonText: "); IonWriter prettyWriter = IonTextWriterBuilder.pretty().build(sb); try { prettyWriter.writeValues(IonReaderBuilder.standard().build(valueHolder.getIonText())); } catch (IOException ioe) { sb.append("**Exception while printing this IonText**"); } } sb.append("}"); return sb.toString(); } /** * Returns the string representation of a given {@link GetBlockResult}. * Adapted from the AWS SDK autogenerated {@code toString()} method, with sensitive values un-redacted. * * @param getBlockResult the {@link GetBlockResult} to convert to a String. * @return the String representation of the supplied {@link GetBlockResult}. */ public static String toUnredactedString(GetBlockResult getBlockResult) { StringBuilder sb = new StringBuilder(); sb.append("{"); if (getBlockResult.getBlock() != null) { sb.append("Block: ").append(toUnredactedString(getBlockResult.getBlock())).append(","); } if (getBlockResult.getProof() != null) { sb.append("Proof: ").append(toUnredactedString(getBlockResult.getProof())); } sb.append("}"); return sb.toString(); } /** * Returns the string representation of a given {@link GetDigestResult}. * Adapted from the AWS SDK autogenerated {@code toString()} method, with sensitive values un-redacted. * * @param getDigestResult the {@link GetDigestResult} to convert to a String. * @return the String representation of the supplied {@link GetDigestResult}. */ public static String toUnredactedString(GetDigestResult getDigestResult) { StringBuilder sb = new StringBuilder(); sb.append("{"); if (getDigestResult.getDigest() != null) { sb.append("Digest: ").append(getDigestResult.getDigest()).append(","); } if (getDigestResult.getDigestTipAddress() != null) { sb.append("DigestTipAddress: ").append(toUnredactedString(getDigestResult.getDigestTipAddress())); } sb.append("}"); return sb.toString(); } }
-
Verifier.java
-
-
2 つの
.java
ファイル (GetDigest.java
およびGetRevision.java
) を使用して、次の手順を実行します。-
vehicle-registration
台帳に新しいダイジェストをリクエストします。 -
VehicleRegistration
テーブルにドキュメントの各リビジョンの証明をリクエストします。 -
返されたダイジェストと証明を使用して、ダイジェストを再計算することで、リビジョンを検証します。
GetDigest.java
プログラムには、次のコードが含まれています。/* * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: MIT-0 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package software.amazon.qldb.tutorial; import com.amazonaws.services.qldb.AmazonQLDB; import com.amazonaws.services.qldb.model.GetDigestRequest; import com.amazonaws.services.qldb.model.GetDigestResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.qldb.tutorial.qldb.QldbStringUtils; /** * This is an example for retrieving the digest of a particular ledger. * * This code expects that you have AWS credentials setup per: * http://docs.aws.amazon.com/java-sdk/latest/developer-guide/setup-credentials.html */ public final class GetDigest { public static final Logger log = LoggerFactory.getLogger(GetDigest.class); public static AmazonQLDB client = CreateLedger.getClient(); private GetDigest() { } /** * Calls {@link #getDigest(String)} for a ledger. * * @param args * Arbitrary command-line arguments. * @throws Exception if failed to get a ledger digest. */ public static void main(final String... args) throws Exception { try { getDigest(Constants.LEDGER_NAME); } catch (Exception e) { log.error("Unable to get a ledger digest!", e); throw e; } } /** * Get the digest for the specified ledger. * * @param ledgerName * The ledger to get digest from. * @return {@link GetDigestResult}. */ public static GetDigestResult getDigest(final String ledgerName) { log.info("Let's get the current digest of the ledger named {}.", ledgerName); GetDigestRequest request = new GetDigestRequest() .withName(ledgerName); GetDigestResult result = client.getDigest(request); log.info("Success. LedgerDigest: {}.", QldbStringUtils.toUnredactedString(result)); return result; } }
注記
getDigest
メソッドを使用して、台帳のジャーナルの現在のティップを含むダイジェストをリクエストします。ジャーナルのティップは、 がリクエストQLDBを受信したときの最新のコミット済みブロックを参照します。GetRevision.java
プログラムには、次のコードが含まれています。注記
getRevision
メソッドが指定されたドキュメントリビジョンの証明を返した後、このプログラムはクライアント側APIを使用してそのリビジョンを検証します。この で使用されるアルゴリズムの概要については、API「」を参照してください証明を使用したダイジェストの再計算。 -
-
プログラムをコンパイルして実行
GetRevision.java
し、 VIN でVehicleRegistration
ドキュメントを暗号的に検証します1N4AL11D75C109151
。
vehicle-registration
台帳でジャーナルデータをエクスポートして検証するには、「ステップ 8: 元帳のジャーナルデータをエクスポートして検証する」に進みます。