Skip to content

Commit 8d95e57

Browse files
committed
sign certificates with RSA SH2 variants
1 parent 49fe1f1 commit 8d95e57

7 files changed

Lines changed: 92 additions & 21 deletions

File tree

lib/ssh_data/certificate.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,12 @@ def rfc4253
148148
# Sign this certificate with a private key.
149149
#
150150
# private_key - An SSHData::PrivateKey::Base subclass instance.
151+
# algo: - Optionally specify the signature algorithm to use.
151152
#
152153
# Returns nothing.
153-
def sign(private_key)
154+
def sign(private_key, algo: nil)
154155
@ca_key = private_key.public_key
155-
@signature = private_key.sign(signed_data)
156+
@signature = private_key.sign(signed_data, algo: algo)
156157
end
157158

158159
# Verify the certificate's signature.

lib/ssh_data/private_key/base.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ def sign(signed_data, algo: nil)
2727

2828
# Issue a certificate using this private key.
2929
#
30-
# kwargs - See SSHData::Certificate.new.
30+
# signature_algo: - Optionally specify the signature algorithm to use.
31+
# kwargs - See SSHData::Certificate.new.
3132
#
3233
# Returns a SSHData::Certificate instance.
33-
def issue_certificate(**kwargs)
34-
Certificate.new(**kwargs).tap { |c| c.sign(self) }
34+
def issue_certificate(signature_algo: nil, **kwargs)
35+
Certificate.new(**kwargs).tap { |c| c.sign(self, algo: signature_algo) }
3536
end
3637
end
3738
end

spec/certificate_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,22 @@
171171
expect(subject.verify).to eq(true)
172172
end
173173

174+
it "can be signed with an RSA key using ALGO_RSA_SHA2_256" do
175+
expect {
176+
subject.sign(rsa_ca, algo: SSHData::PublicKey::ALGO_RSA_SHA2_256)
177+
}.to change {subject.signature}
178+
179+
expect(subject.verify).to eq(true)
180+
end
181+
182+
it "can be signed with an RSA key using ALGO_RSA_SHA2_512" do
183+
expect {
184+
subject.sign(rsa_ca, algo: SSHData::PublicKey::ALGO_RSA_SHA2_512)
185+
}.to change {subject.signature}
186+
187+
expect(subject.verify).to eq(true)
188+
end
189+
174190
it "can be signed with an DSA key" do
175191
expect { subject.sign(dsa_ca) }.to change {subject.signature}
176192
expect(subject.verify).to eq(true)

spec/private_key/dsa_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
let(:public_key) { private_key.public_key }
66
let(:params) { private_key.params }
77
let(:message) { "hello, world!" }
8+
let(:cert_key) { SSHData::PrivateKey::DSA.generate.public_key }
89

910
let(:openssh_key) { SSHData::PrivateKey.parse(fixture("dsa_leaf_for_rsa_ca")) }
1011

@@ -35,6 +36,16 @@
3536
}.to raise_error(SSHData::AlgorithmError)
3637
end
3738

39+
it "raises when trying to sign with bad algo" do
40+
expect {
41+
subject.issue_certificate(
42+
public_key: cert_key,
43+
key_id: "some ident",
44+
signature_algo: SSHData::PublicKey::ALGO_RSA
45+
)
46+
}.to raise_error(SSHData::AlgorithmError)
47+
end
48+
3849
it "has an algo" do
3950
expect(subject.algo).to eq(SSHData::PublicKey::ALGO_DSA)
4051
end

spec/private_key/ecdsa_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
describe SSHData::PrivateKey::ECDSA do
44
let(:openssh_key) { SSHData::PrivateKey.parse(fixture("ecdsa_leaf_for_rsa_ca")) }
5+
let(:cert_key) { SSHData::PrivateKey::DSA.generate.public_key }
56

67
it "can raises AlgorithmError for unknown curves" do
78
expect {
@@ -48,6 +49,16 @@
4849
}.to raise_error(SSHData::AlgorithmError)
4950
end
5051

52+
it "raises when trying to sign with bad algo" do
53+
expect {
54+
subject.issue_certificate(
55+
public_key: cert_key,
56+
key_id: "some ident",
57+
signature_algo: SSHData::PublicKey::ALGO_RSA
58+
)
59+
}.to raise_error(SSHData::AlgorithmError)
60+
end
61+
5162
it "has an algo" do
5263
expect(subject.algo).to eq(algo)
5364
end

spec/private_key/ed25519_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
let(:verify_key) { signing_key.verify_key }
66
let(:comment) { "asdf" }
77
let(:message) { "hello, world!" }
8+
let(:cert_key) { SSHData::PrivateKey::DSA.generate.public_key }
89

910
let(:openssh_key) { SSHData::PrivateKey.parse(fixture("ed25519_leaf_for_rsa_ca")) }
1011

@@ -38,6 +39,16 @@
3839
}.to raise_error(SSHData::AlgorithmError)
3940
end
4041

42+
it "raises when trying to sign with bad algo" do
43+
expect {
44+
subject.issue_certificate(
45+
public_key: cert_key,
46+
key_id: "some ident",
47+
signature_algo: SSHData::PublicKey::ALGO_RSA
48+
)
49+
}.to raise_error(SSHData::AlgorithmError)
50+
end
51+
4152
it "has an algo" do
4253
expect(subject.algo).to eq(SSHData::PublicKey::ALGO_ED25519)
4354
end

spec/private_key/rsa_spec.rb

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
let(:public_key) { private_key.public_key }
66
let(:params) { private_key.params }
77
let(:message) { "hello, world!" }
8+
let(:cert_key) { SSHData::PrivateKey::DSA.generate.public_key }
89

910
let(:openssh_key) { SSHData::PrivateKey.parse(fixture("rsa_leaf_for_rsa_ca")) }
1011

@@ -28,26 +29,45 @@
2829
}.not_to raise_error
2930
end
3031

31-
it "can sign messages" do
32-
expect(subject.public_key.verify(message, subject.sign(message))).to eq(true)
32+
[
33+
nil,
34+
SSHData::PublicKey::ALGO_RSA,
35+
SSHData::PublicKey::ALGO_RSA_SHA2_256,
36+
SSHData::PublicKey::ALGO_RSA_SHA2_512
37+
].each do |signature_algo|
38+
it "can sign messages with #{signature_algo}" do
39+
sig = subject.sign(message, algo: signature_algo)
40+
expect(subject.public_key.verify(message, sig)).to eq(true)
41+
42+
algo, _ = SSHData::Encoding.decode_signature(sig)
43+
expect(algo).to eq(signature_algo || SSHData::PublicKey::ALGO_RSA)
44+
end
45+
46+
it "can issue a certificate with a #{signature_algo} signature" do
47+
cert = subject.issue_certificate(
48+
public_key: cert_key,
49+
key_id: "some ident",
50+
signature_algo: signature_algo
51+
)
52+
53+
algo, _ = SSHData::Encoding.decode_signature(cert.signature)
54+
55+
expect(algo).to eq(signature_algo || SSHData::PublicKey::ALGO_RSA)
56+
expect(cert.verify).to be(true)
57+
end
3358
end
3459

35-
it "can sign messages with ALGO_RSA" do
36-
sig = subject.sign(message, algo: SSHData::PublicKey::ALGO_RSA)
37-
expect(subject.public_key.verify(message, sig)).to eq(true)
38-
end
39-
40-
it "can sign messages with ALGO_RSA_SHA2_256" do
41-
sig = subject.sign(message, algo: SSHData::PublicKey::ALGO_RSA_SHA2_256)
42-
expect(subject.public_key.verify(message, sig)).to eq(true)
43-
end
44-
45-
it "can sign messages with ALGO_RSA_SHA2_512" do
46-
sig = subject.sign(message, algo: SSHData::PublicKey::ALGO_RSA_SHA2_512)
47-
expect(subject.public_key.verify(message, sig)).to eq(true)
60+
it "raises when trying to sign with bad algo" do
61+
expect {
62+
subject.issue_certificate(
63+
public_key: cert_key,
64+
key_id: "some ident",
65+
signature_algo: SSHData::PublicKey::ALGO_DSA
66+
)
67+
}.to raise_error(SSHData::AlgorithmError)
4868
end
4969

50-
it "raises when trying to sign with bad algo" do
70+
it "raises when trying to issue a certificate with bad signature algo" do
5171
expect {
5272
subject.sign(message, algo: SSHData::PublicKey::ALGO_DSA)
5373
}.to raise_error(SSHData::AlgorithmError)

0 commit comments

Comments
 (0)