Browse Source
This change introduces the concept of a GpgSigner which will sign commits. The GpgSigner will be of a specific implementation (eg., Bouncycastle or OpenPgP executable). The actual implementation is not part of this change. Bug: 382212 Change-Id: Iea5da1e885c039e06bc8d679d46b124cbe504c8e Also-by: Medha Bhargav Prabhala <mprabhala@salesforce.com> Signed-off-by: Medha Bhargav Prabhala <mprabhala@salesforce.com> Signed-off-by: Gunnar Wagenknecht <gunnar@wagenknecht.org>stable-5.3
Gunnar Wagenknecht
6 years ago
9 changed files with 735 additions and 1 deletions
@ -0,0 +1,201 @@
|
||||
/* |
||||
* Copyright (C) 2018, Salesforce. |
||||
* and other copyright owners as documented in the project's IP log. |
||||
* |
||||
* This program and the accompanying materials are made available |
||||
* under the terms of the Eclipse Distribution License v1.0 which |
||||
* accompanies this distribution, is reproduced below, and is |
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
* |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or |
||||
* without modification, are permitted provided that the following |
||||
* conditions are met: |
||||
* |
||||
* - Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* - Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following |
||||
* disclaimer in the documentation and/or other materials provided |
||||
* with the distribution. |
||||
* |
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the |
||||
* names of its contributors may be used to endorse or promote |
||||
* products derived from this software without specific prior |
||||
* written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package org.eclipse.jgit.lib; |
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII; |
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNull; |
||||
import static org.junit.Assert.assertSame; |
||||
import static org.junit.Assert.fail; |
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.IOException; |
||||
import java.text.MessageFormat; |
||||
|
||||
import org.eclipse.jgit.internal.JGitText; |
||||
import org.junit.Test; |
||||
|
||||
public class CommitBuilderTest { |
||||
|
||||
private void assertGpgSignatureStringOutcome(String signature, |
||||
String expectedOutcome) throws IOException { |
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
||||
CommitBuilder.writeGpgSignatureString(signature, out); |
||||
String formatted_signature = new String(out.toByteArray(), US_ASCII); |
||||
assertEquals(expectedOutcome, formatted_signature); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_1() throws Exception { |
||||
// @formatter:off
|
||||
String signature = "-----BEGIN PGP SIGNATURE-----\n" + |
||||
"Version: BCPG v1.60\n" + |
||||
"\n" + |
||||
"iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + |
||||
"opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + |
||||
"gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + |
||||
"uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + |
||||
"3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + |
||||
"IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + |
||||
"=b9OI\n" + |
||||
"-----END PGP SIGNATURE-----"; |
||||
String expectedOutcome = "-----BEGIN PGP SIGNATURE-----\n" + |
||||
" Version: BCPG v1.60\n" + |
||||
" \n" + |
||||
" iQEcBAABCAAGBQJb9cVhAAoJEKX+6Axg/6TZeFsH/0CY0WX/z7U8+7S5giFX4wH4\n" + |
||||
" opvBwqyt6OX8lgNwTwBGHFNt8LdmDCCmKoq/XwkNi3ARVjLhe3gBcKXNoavvPk2Z\n" + |
||||
" gIg5ChevGkU4afWCOMLVEYnkCBGw2+86XhrK1P7gTHEk1Rd+Yv1ZRDJBY+fFO7yz\n" + |
||||
" uSBuF5RpEY2sJiIvp27Gub/rY3B5NTR/feO/z+b9oiP/fMUhpRwG5KuWUsn9NPjw\n" + |
||||
" 3tvbgawYpU/2UnS+xnavMY4t2fjRYjsoxndPLb2MUX8X7vC7FgWLBlmI/rquLZVM\n" + |
||||
" IQEKkjnA+lhejjK1rv+ulq4kGZJFKGYWYYhRDwFg5PTkzhudhN2SGUq5Wxq1Eg4=\n" + |
||||
" =b9OI\n" + |
||||
" -----END PGP SIGNATURE-----"; |
||||
// @formatter:on
|
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_failsForNonAscii() throws Exception { |
||||
String signature = "Ü Ä"; |
||||
try { |
||||
CommitBuilder.writeGpgSignatureString(signature, |
||||
new ByteArrayOutputStream()); |
||||
fail("Exception expected"); |
||||
} catch (IllegalArgumentException e) { |
||||
// good
|
||||
String message = MessageFormat.format(JGitText.get().notASCIIString, |
||||
signature); |
||||
assertEquals(message, e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_oneLineNotModified() throws Exception { |
||||
String signature = " A string "; |
||||
String expectedOutcome = signature; |
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_preservesRandomWhitespace() |
||||
throws Exception { |
||||
// @formatter:off
|
||||
String signature = " String with \n" |
||||
+ "Line 2\n" |
||||
+ " Line 3\n" |
||||
+ "Line 4 \n" |
||||
+ " Line 5 "; |
||||
String expectedOutcome = " String with \n" |
||||
+ " Line 2\n" |
||||
+ " Line 3\n" |
||||
+ " Line 4 \n" |
||||
+ " Line 5 "; |
||||
// @formatter:on
|
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_replaceCR() throws Exception { |
||||
// @formatter:off
|
||||
String signature = "String with \r" |
||||
+ "Line 2\r" |
||||
+ "Line 3\r" |
||||
+ "Line 4\r" |
||||
+ "Line 5"; |
||||
String expectedOutcome = "String with \n" |
||||
+ " Line 2\n" |
||||
+ " Line 3\n" |
||||
+ " Line 4\n" |
||||
+ " Line 5"; |
||||
// @formatter:on
|
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_replaceCRLF() throws Exception { |
||||
// @formatter:off
|
||||
String signature = "String with \r\n" |
||||
+ "Line 2\r\n" |
||||
+ "Line 3\r\n" |
||||
+ "Line 4\r\n" |
||||
+ "Line 5"; |
||||
String expectedOutcome = "String with \n" |
||||
+ " Line 2\n" |
||||
+ " Line 3\n" |
||||
+ " Line 4\n" |
||||
+ " Line 5"; |
||||
// @formatter:on
|
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void writeGpgSignatureString_replaceCRLFMixed() throws Exception { |
||||
// @formatter:off
|
||||
String signature = "String with \r" |
||||
+ "Line 2\r\n" |
||||
+ "Line 3\r" |
||||
+ "Line 4\r\n" |
||||
+ "Line 5"; |
||||
String expectedOutcome = "String with \n" |
||||
+ " Line 2\n" |
||||
+ " Line 3\n" |
||||
+ " Line 4\n" |
||||
+ " Line 5"; |
||||
// @formatter:on
|
||||
assertGpgSignatureStringOutcome(signature, expectedOutcome); |
||||
} |
||||
|
||||
@Test |
||||
public void setGpgSignature() throws Exception { |
||||
GpgSignature dummy = new GpgSignature(new byte[0]); |
||||
|
||||
CommitBuilder builder = new CommitBuilder(); |
||||
assertNull(builder.getGpgSignature()); |
||||
|
||||
builder.setGpgSignature(dummy); |
||||
assertSame(dummy, builder.getGpgSignature()); |
||||
|
||||
builder.setGpgSignature(null); |
||||
assertNull(builder.getGpgSignature()); |
||||
} |
||||
} |
@ -0,0 +1,69 @@
|
||||
/* |
||||
* Copyright (C) 2018, Salesforce and |
||||
* other copyright owners as documented in the project's IP log. |
||||
* |
||||
* This program and the accompanying materials are made available under the |
||||
* terms of the Eclipse Distribution License v1.0 which accompanies this |
||||
* distribution, is reproduced below, and is available at |
||||
* http://www.eclipse.org/org/documents/edl-v10.php
|
||||
* |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are met: |
||||
* |
||||
* - Redistributions of source code must retain the above copyright notice, this |
||||
* list of conditions and the following disclaimer. |
||||
* |
||||
* - Redistributions in binary form must reproduce the above copyright notice, |
||||
* this list of conditions and the following disclaimer in the documentation |
||||
* and/or other materials provided with the distribution. |
||||
* |
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from this |
||||
* software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||
* POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package org.eclipse.jgit.api.errors; |
||||
|
||||
/** |
||||
* Exception thrown when the configured gpg.format is not supported. |
||||
* |
||||
* @since 5.3 |
||||
*/ |
||||
public class UnsupportedSigningFormatException extends GitAPIException { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
/** |
||||
* Constructor for UnsupportedGpgFormatException |
||||
* |
||||
* @param message |
||||
* error message |
||||
* @param cause |
||||
* a {@link java.lang.Throwable} |
||||
*/ |
||||
public UnsupportedSigningFormatException(String message, Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
|
||||
/** |
||||
* Constructor for UnsupportedGpgFormatException |
||||
* |
||||
* @param message |
||||
* error message |
||||
*/ |
||||
public UnsupportedSigningFormatException(String message) { |
||||
super(message); |
||||
} |
||||
} |
@ -0,0 +1,98 @@
|
||||
/* |
||||
* Copyright (C) 2018, Salesforce. |
||||
* and other copyright owners as documented in the project's IP log. |
||||
* |
||||
* This program and the accompanying materials are made available |
||||
* under the terms of the Eclipse Distribution License v1.0 which |
||||
* accompanies this distribution, is reproduced below, and is |
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
* |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or |
||||
* without modification, are permitted provided that the following |
||||
* conditions are met: |
||||
* |
||||
* - Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* - Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following |
||||
* disclaimer in the documentation and/or other materials provided |
||||
* with the distribution. |
||||
* |
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the |
||||
* names of its contributors may be used to endorse or promote |
||||
* products derived from this software without specific prior |
||||
* written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package org.eclipse.jgit.lib; |
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
import org.eclipse.jgit.annotations.NonNull; |
||||
|
||||
/** |
||||
* A structure for holding GPG signature together with additional related data. |
||||
* |
||||
* @since 5.3 |
||||
*/ |
||||
public class GpgSignature implements Serializable { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private byte[] signature; |
||||
|
||||
/** |
||||
* Creates a new instance with the specified signature |
||||
* |
||||
* @param signature |
||||
* the signature |
||||
*/ |
||||
public GpgSignature(@NonNull byte[] signature) { |
||||
this.signature = signature; |
||||
} |
||||
|
||||
/** |
||||
* Format for Git storage. |
||||
* <p> |
||||
* This returns the ASCII Armor as per |
||||
* https://tools.ietf.org/html/rfc4880#section-6.2.
|
||||
* </p> |
||||
* |
||||
* @return a string of the signature ready to be embedded in a Git object |
||||
*/ |
||||
public String toExternalString() { |
||||
return new String(signature, US_ASCII); |
||||
} |
||||
|
||||
/** {@inheritDoc} */ |
||||
@Override |
||||
@SuppressWarnings("nls") |
||||
public String toString() { |
||||
final StringBuilder r = new StringBuilder(); |
||||
|
||||
r.append("GpgSignature["); |
||||
r.append( |
||||
this.signature != null ? "length " + signature.length : "null"); |
||||
r.append("]"); |
||||
|
||||
return r.toString(); |
||||
} |
||||
} |
@ -0,0 +1,100 @@
|
||||
/* |
||||
* Copyright (C) 2018, Salesforce. |
||||
* and other copyright owners as documented in the project's IP log. |
||||
* |
||||
* This program and the accompanying materials are made available |
||||
* under the terms of the Eclipse Distribution License v1.0 which |
||||
* accompanies this distribution, is reproduced below, and is |
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
* |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or |
||||
* without modification, are permitted provided that the following |
||||
* conditions are met: |
||||
* |
||||
* - Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* - Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following |
||||
* disclaimer in the documentation and/or other materials provided |
||||
* with the distribution. |
||||
* |
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the |
||||
* names of its contributors may be used to endorse or promote |
||||
* products derived from this software without specific prior |
||||
* written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
package org.eclipse.jgit.lib; |
||||
|
||||
import org.eclipse.jgit.annotations.NonNull; |
||||
|
||||
/** |
||||
* Creates GPG signatures for Git objects. |
||||
* |
||||
* @since 5.3 |
||||
*/ |
||||
public abstract class GpgSigner { |
||||
|
||||
private static GpgSigner defaultSigner; |
||||
|
||||
/** |
||||
* Get the default signer, or <code>null</code>. |
||||
* |
||||
* @return the default signer, or <code>null</code>. |
||||
*/ |
||||
public static GpgSigner getDefault() { |
||||
return defaultSigner; |
||||
} |
||||
|
||||
/** |
||||
* Set the default signer. |
||||
* |
||||
* @param signer |
||||
* the new default signer, may be <code>null</code> to select no |
||||
* default. |
||||
*/ |
||||
public static void setDefault(GpgSigner signer) { |
||||
GpgSigner.defaultSigner = signer; |
||||
} |
||||
|
||||
/** |
||||
* Signs the specified commit. |
||||
* |
||||
* <p> |
||||
* Implementors should obtain the payload for signing from the specified |
||||
* commit via {@link CommitBuilder#build()} and create a proper |
||||
* {@link GpgSignature}. The generated signature must be set on the |
||||
* specified {@code commit} (see |
||||
* {@link CommitBuilder#setGpgSignature(GpgSignature)}). |
||||
* </p> |
||||
* <p> |
||||
* Any existing signature on the commit must be discarded prior obtaining |
||||
* the payload via {@link CommitBuilder#build()}. |
||||
* </p> |
||||
* |
||||
* @param commit |
||||
* the commit to sign (must not be <code>null</code> and must be |
||||
* complete to allow proper calculation of payload) |
||||
* @param gpgSigningKey |
||||
* the signing key (passed as is to the GPG signing tool) |
||||
*/ |
||||
public abstract void sign(@NonNull CommitBuilder commit, |
||||
String gpgSigningKey); |
||||
|
||||
} |
Loading…
Reference in new issue